| 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/adapters.h" | 10 #include "src/base/adapters.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 #include "src/isolate-inl.h" | 66 #include "src/isolate-inl.h" |
| 67 #include "src/ostreams.h" | 67 #include "src/ostreams.h" |
| 68 #include "src/register-configuration.h" | 68 #include "src/register-configuration.h" |
| 69 #include "src/type-info.h" | 69 #include "src/type-info.h" |
| 70 #include "src/utils.h" | 70 #include "src/utils.h" |
| 71 | 71 |
| 72 namespace v8 { | 72 namespace v8 { |
| 73 namespace internal { | 73 namespace internal { |
| 74 namespace compiler { | 74 namespace compiler { |
| 75 | 75 |
| 76 class PipelineData : public ZoneObject { | 76 class PipelineData { |
| 77 public: | 77 public: |
| 78 // For main entry point. | 78 // For main entry point. |
| 79 PipelineData(ZonePool* zone_pool, CompilationInfo* info, | 79 PipelineData(ZonePool* zone_pool, CompilationInfo* info, |
| 80 PipelineStatistics* pipeline_statistics) | 80 PipelineStatistics* pipeline_statistics) |
| 81 : isolate_(info->isolate()), | 81 : isolate_(info->isolate()), |
| 82 info_(info), | 82 info_(info), |
| 83 outer_zone_(info_->zone()), | 83 outer_zone_(info_->zone()), |
| 84 zone_pool_(zone_pool), | 84 zone_pool_(zone_pool), |
| 85 pipeline_statistics_(pipeline_statistics), | 85 pipeline_statistics_(pipeline_statistics), |
| 86 graph_zone_scope_(zone_pool_), | 86 graph_zone_scope_(zone_pool_), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 101 jsgraph_ = new (graph_zone_) | 101 jsgraph_ = new (graph_zone_) |
| 102 JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_); | 102 JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_); |
| 103 } | 103 } |
| 104 | 104 |
| 105 // For WASM compile entry point. | 105 // For WASM compile entry point. |
| 106 PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph, | 106 PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph, |
| 107 SourcePositionTable* source_positions) | 107 SourcePositionTable* source_positions) |
| 108 : isolate_(info->isolate()), | 108 : isolate_(info->isolate()), |
| 109 info_(info), | 109 info_(info), |
| 110 zone_pool_(zone_pool), | 110 zone_pool_(zone_pool), |
| 111 pipeline_statistics_(nullptr), |
| 111 graph_zone_scope_(zone_pool_), | 112 graph_zone_scope_(zone_pool_), |
| 112 graph_(graph), | 113 graph_(graph), |
| 113 source_positions_(source_positions), | 114 source_positions_(new (info->zone()) SourcePositionTable(graph_)), |
| 114 instruction_zone_scope_(zone_pool_), | 115 instruction_zone_scope_(zone_pool_), |
| 115 instruction_zone_(instruction_zone_scope_.zone()), | 116 instruction_zone_(instruction_zone_scope_.zone()), |
| 116 register_allocation_zone_scope_(zone_pool_), | 117 register_allocation_zone_scope_(zone_pool_), |
| 117 register_allocation_zone_(register_allocation_zone_scope_.zone()) {} | 118 register_allocation_zone_(register_allocation_zone_scope_.zone()) {} |
| 118 | 119 |
| 119 // For machine graph testing entry point. | 120 // For machine graph testing entry point. |
| 120 PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph, | 121 PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph, |
| 121 Schedule* schedule) | 122 Schedule* schedule) |
| 122 : isolate_(info->isolate()), | 123 : isolate_(info->isolate()), |
| 123 info_(info), | 124 info_(info), |
| 124 zone_pool_(zone_pool), | 125 zone_pool_(zone_pool), |
| 126 pipeline_statistics_(nullptr), |
| 125 graph_zone_scope_(zone_pool_), | 127 graph_zone_scope_(zone_pool_), |
| 126 graph_(graph), | 128 graph_(graph), |
| 127 source_positions_(new (info->zone()) SourcePositionTable(graph_)), | 129 source_positions_(new (info->zone()) SourcePositionTable(graph_)), |
| 128 schedule_(schedule), | 130 schedule_(schedule), |
| 129 instruction_zone_scope_(zone_pool_), | 131 instruction_zone_scope_(zone_pool_), |
| 130 instruction_zone_(instruction_zone_scope_.zone()), | 132 instruction_zone_(instruction_zone_scope_.zone()), |
| 131 register_allocation_zone_scope_(zone_pool_), | 133 register_allocation_zone_scope_(zone_pool_), |
| 132 register_allocation_zone_(register_allocation_zone_scope_.zone()) {} | 134 register_allocation_zone_(register_allocation_zone_scope_.zone()) {} |
| 133 | 135 |
| 134 // For register allocation testing entry point. | 136 // For register allocation testing entry point. |
| 135 PipelineData(ZonePool* zone_pool, CompilationInfo* info, | 137 PipelineData(ZonePool* zone_pool, CompilationInfo* info, |
| 136 InstructionSequence* sequence) | 138 InstructionSequence* sequence) |
| 137 : isolate_(info->isolate()), | 139 : isolate_(info->isolate()), |
| 138 info_(info), | 140 info_(info), |
| 139 zone_pool_(zone_pool), | 141 zone_pool_(zone_pool), |
| 142 pipeline_statistics_(nullptr), |
| 140 graph_zone_scope_(zone_pool_), | 143 graph_zone_scope_(zone_pool_), |
| 141 instruction_zone_scope_(zone_pool_), | 144 instruction_zone_scope_(zone_pool_), |
| 142 instruction_zone_(sequence->zone()), | 145 instruction_zone_(sequence->zone()), |
| 143 sequence_(sequence), | 146 sequence_(sequence), |
| 144 register_allocation_zone_scope_(zone_pool_), | 147 register_allocation_zone_scope_(zone_pool_), |
| 145 register_allocation_zone_(register_allocation_zone_scope_.zone()) {} | 148 register_allocation_zone_(register_allocation_zone_scope_.zone()) {} |
| 146 | 149 |
| 147 void Destroy() { | 150 ~PipelineData() { |
| 148 DeleteRegisterAllocationZone(); | 151 DeleteRegisterAllocationZone(); |
| 149 DeleteInstructionZone(); | 152 DeleteInstructionZone(); |
| 150 DeleteGraphZone(); | 153 DeleteGraphZone(); |
| 151 } | 154 } |
| 152 | 155 |
| 153 ~PipelineData() { Destroy(); } | |
| 154 | |
| 155 Isolate* isolate() const { return isolate_; } | 156 Isolate* isolate() const { return isolate_; } |
| 156 CompilationInfo* info() const { return info_; } | 157 CompilationInfo* info() const { return info_; } |
| 157 ZonePool* zone_pool() const { return zone_pool_; } | 158 ZonePool* zone_pool() const { return zone_pool_; } |
| 158 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } | 159 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } |
| 159 bool compilation_failed() const { return compilation_failed_; } | 160 bool compilation_failed() const { return compilation_failed_; } |
| 160 void set_compilation_failed() { compilation_failed_ = true; } | 161 void set_compilation_failed() { compilation_failed_ = true; } |
| 161 Handle<Code> code() { return code_; } | 162 Handle<Code> code() { return code_; } |
| 162 void set_code(Handle<Code> code) { | 163 void set_code(Handle<Code> code) { |
| 163 DCHECK(code_.is_null()); | 164 DCHECK(code_.is_null()); |
| 164 code_ = code; | 165 code_ = code; |
| 165 } | 166 } |
| 166 BasicBlockProfiler::Data* profiler_data() { return profiler_data_; } | 167 |
| 167 void set_profiler_data(BasicBlockProfiler::Data* data) { | |
| 168 profiler_data_ = data; | |
| 169 } | |
| 170 std::ostringstream* source_position_output() { | |
| 171 return &source_position_output_; | |
| 172 } | |
| 173 // RawMachineAssembler generally produces graphs which cannot be verified. | 168 // RawMachineAssembler generally produces graphs which cannot be verified. |
| 174 bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } | 169 bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } |
| 175 | 170 |
| 176 Zone* graph_zone() const { return graph_zone_; } | 171 Zone* graph_zone() const { return graph_zone_; } |
| 177 Graph* graph() const { return graph_; } | 172 Graph* graph() const { return graph_; } |
| 178 SourcePositionTable* source_positions() const { | 173 SourcePositionTable* source_positions() const { return source_positions_; } |
| 179 DCHECK_NOT_NULL(source_positions_); | |
| 180 return source_positions_; | |
| 181 } | |
| 182 MachineOperatorBuilder* machine() const { return machine_; } | 174 MachineOperatorBuilder* machine() const { return machine_; } |
| 183 CommonOperatorBuilder* common() const { return common_; } | 175 CommonOperatorBuilder* common() const { return common_; } |
| 184 JSOperatorBuilder* javascript() const { return javascript_; } | 176 JSOperatorBuilder* javascript() const { return javascript_; } |
| 185 JSGraph* jsgraph() const { return jsgraph_; } | 177 JSGraph* jsgraph() const { return jsgraph_; } |
| 186 MaybeHandle<Context> native_context() const { | 178 MaybeHandle<Context> native_context() const { |
| 187 if (info()->is_native_context_specializing()) { | 179 if (info()->is_native_context_specializing()) { |
| 188 return handle(info()->native_context(), isolate()); | 180 return handle(info()->native_context(), isolate()); |
| 189 } | 181 } |
| 190 return MaybeHandle<Context>(); | 182 return MaybeHandle<Context>(); |
| 191 } | 183 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 211 | 203 |
| 212 Zone* instruction_zone() const { return instruction_zone_; } | 204 Zone* instruction_zone() const { return instruction_zone_; } |
| 213 InstructionSequence* sequence() const { return sequence_; } | 205 InstructionSequence* sequence() const { return sequence_; } |
| 214 Frame* frame() const { return frame_; } | 206 Frame* frame() const { return frame_; } |
| 215 | 207 |
| 216 Zone* register_allocation_zone() const { return register_allocation_zone_; } | 208 Zone* register_allocation_zone() const { return register_allocation_zone_; } |
| 217 RegisterAllocationData* register_allocation_data() const { | 209 RegisterAllocationData* register_allocation_data() const { |
| 218 return register_allocation_data_; | 210 return register_allocation_data_; |
| 219 } | 211 } |
| 220 | 212 |
| 213 BasicBlockProfiler::Data* profiler_data() const { return profiler_data_; } |
| 214 void set_profiler_data(BasicBlockProfiler::Data* profiler_data) { |
| 215 profiler_data_ = profiler_data; |
| 216 } |
| 217 |
| 218 std::string const& source_position_output() const { |
| 219 return source_position_output_; |
| 220 } |
| 221 void set_source_position_output(std::string const& source_position_output) { |
| 222 source_position_output_ = source_position_output; |
| 223 } |
| 224 |
| 221 void DeleteGraphZone() { | 225 void DeleteGraphZone() { |
| 222 if (graph_zone_ == nullptr) return; | 226 if (graph_zone_ == nullptr) return; |
| 223 graph_zone_scope_.Destroy(); | 227 graph_zone_scope_.Destroy(); |
| 224 graph_zone_ = nullptr; | 228 graph_zone_ = nullptr; |
| 225 graph_ = nullptr; | 229 graph_ = nullptr; |
| 226 source_positions_ = nullptr; | 230 source_positions_ = nullptr; |
| 227 loop_assignment_ = nullptr; | 231 loop_assignment_ = nullptr; |
| 228 type_hint_analysis_ = nullptr; | 232 type_hint_analysis_ = nullptr; |
| 229 simplified_ = nullptr; | 233 simplified_ = nullptr; |
| 230 machine_ = nullptr; | 234 machine_ = nullptr; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 void InitializeRegisterAllocationData(const RegisterConfiguration* config, | 280 void InitializeRegisterAllocationData(const RegisterConfiguration* config, |
| 277 CallDescriptor* descriptor, | 281 CallDescriptor* descriptor, |
| 278 const char* debug_name) { | 282 const char* debug_name) { |
| 279 DCHECK(register_allocation_data_ == nullptr); | 283 DCHECK(register_allocation_data_ == nullptr); |
| 280 register_allocation_data_ = new (register_allocation_zone()) | 284 register_allocation_data_ = new (register_allocation_zone()) |
| 281 RegisterAllocationData(config, register_allocation_zone(), frame(), | 285 RegisterAllocationData(config, register_allocation_zone(), frame(), |
| 282 sequence(), debug_name); | 286 sequence(), debug_name); |
| 283 } | 287 } |
| 284 | 288 |
| 285 private: | 289 private: |
| 286 Isolate* isolate_; | 290 Isolate* const isolate_; |
| 287 CompilationInfo* info_; | 291 CompilationInfo* const info_; |
| 288 Zone* outer_zone_ = nullptr; | 292 Zone* outer_zone_ = nullptr; |
| 289 ZonePool* const zone_pool_; | 293 ZonePool* const zone_pool_; |
| 290 PipelineStatistics* pipeline_statistics_ = nullptr; | 294 PipelineStatistics* pipeline_statistics_; |
| 291 bool compilation_failed_ = false; | 295 bool compilation_failed_ = false; |
| 292 Handle<Code> code_; | 296 Handle<Code> code_ = Handle<Code>::null(); |
| 293 BasicBlockProfiler::Data* profiler_data_ = nullptr; | |
| 294 std::ostringstream source_position_output_; | |
| 295 | 297 |
| 296 // All objects in the following group of fields are allocated in graph_zone_. | 298 // All objects in the following group of fields are allocated in graph_zone_. |
| 297 // They are all set to nullptr when the graph_zone_ is destroyed. | 299 // They are all set to nullptr when the graph_zone_ is destroyed. |
| 298 ZonePool::Scope graph_zone_scope_; | 300 ZonePool::Scope graph_zone_scope_; |
| 299 Zone* graph_zone_ = nullptr; | 301 Zone* graph_zone_ = nullptr; |
| 300 Graph* graph_ = nullptr; | 302 Graph* graph_ = nullptr; |
| 301 SourcePositionTable* source_positions_ = nullptr; | 303 SourcePositionTable* source_positions_ = nullptr; |
| 302 LoopAssignmentAnalysis* loop_assignment_ = nullptr; | 304 LoopAssignmentAnalysis* loop_assignment_ = nullptr; |
| 303 TypeHintAnalysis* type_hint_analysis_ = nullptr; | 305 TypeHintAnalysis* type_hint_analysis_ = nullptr; |
| 304 SimplifiedOperatorBuilder* simplified_ = nullptr; | 306 SimplifiedOperatorBuilder* simplified_ = nullptr; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 317 InstructionSequence* sequence_ = nullptr; | 319 InstructionSequence* sequence_ = nullptr; |
| 318 Frame* frame_ = nullptr; | 320 Frame* frame_ = nullptr; |
| 319 | 321 |
| 320 // All objects in the following group of fields are allocated in | 322 // All objects in the following group of fields are allocated in |
| 321 // register_allocation_zone_. They are all set to nullptr when the zone is | 323 // register_allocation_zone_. They are all set to nullptr when the zone is |
| 322 // destroyed. | 324 // destroyed. |
| 323 ZonePool::Scope register_allocation_zone_scope_; | 325 ZonePool::Scope register_allocation_zone_scope_; |
| 324 Zone* register_allocation_zone_; | 326 Zone* register_allocation_zone_; |
| 325 RegisterAllocationData* register_allocation_data_ = nullptr; | 327 RegisterAllocationData* register_allocation_data_ = nullptr; |
| 326 | 328 |
| 329 // Basic block profiling support. |
| 330 BasicBlockProfiler::Data* profiler_data_ = nullptr; |
| 331 |
| 332 // Source position output for --trace-turbo. |
| 333 std::string source_position_output_; |
| 334 |
| 327 int CalculateFixedFrameSize(CallDescriptor* descriptor) { | 335 int CalculateFixedFrameSize(CallDescriptor* descriptor) { |
| 328 if (descriptor->IsJSFunctionCall()) { | 336 if (descriptor->IsJSFunctionCall()) { |
| 329 return StandardFrameConstants::kFixedSlotCount; | 337 return StandardFrameConstants::kFixedSlotCount; |
| 330 } | 338 } |
| 331 return descriptor->IsCFunctionCall() | 339 return descriptor->IsCFunctionCall() |
| 332 ? (CommonFrameConstants::kFixedSlotCountAboveFp + | 340 ? (CommonFrameConstants::kFixedSlotCountAboveFp + |
| 333 CommonFrameConstants::kCPSlotCount) | 341 CommonFrameConstants::kCPSlotCount) |
| 334 : TypedFrameConstants::kFixedSlotCount; | 342 : TypedFrameConstants::kFixedSlotCount; |
| 335 } | 343 } |
| 336 | 344 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 phase_name), | 460 phase_name), |
| 453 zone_scope_(data->zone_pool()) {} | 461 zone_scope_(data->zone_pool()) {} |
| 454 | 462 |
| 455 Zone* zone() { return zone_scope_.zone(); } | 463 Zone* zone() { return zone_scope_.zone(); } |
| 456 | 464 |
| 457 private: | 465 private: |
| 458 PhaseScope phase_scope_; | 466 PhaseScope phase_scope_; |
| 459 ZonePool::Scope zone_scope_; | 467 ZonePool::Scope zone_scope_; |
| 460 }; | 468 }; |
| 461 | 469 |
| 462 class PipelineCompilationJob : public OptimizedCompileJob { | 470 PipelineStatistics* CreatePipelineStatistics(CompilationInfo* info, |
| 471 ZonePool* zone_pool) { |
| 472 if (!FLAG_turbo_stats) return nullptr; |
| 473 |
| 474 PipelineStatistics* pipeline_statistics = |
| 475 new PipelineStatistics(info, zone_pool); |
| 476 pipeline_statistics->BeginPhaseKind("initializing"); |
| 477 |
| 478 FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "w+"); |
| 479 if (json_file != nullptr) { |
| 480 OFStream json_of(json_file); |
| 481 Handle<Script> script = info->script(); |
| 482 base::SmartArrayPointer<char> function_name = info->GetDebugName(); |
| 483 int pos = info->shared_info()->start_position(); |
| 484 json_of << "{\"function\":\"" << function_name.get() |
| 485 << "\", \"sourcePosition\":" << pos << ", \"source\":\""; |
| 486 if (!script->IsUndefined() && !script->source()->IsUndefined()) { |
| 487 DisallowHeapAllocation no_allocation; |
| 488 int start = info->shared_info()->start_position(); |
| 489 int len = info->shared_info()->end_position() - start; |
| 490 String::SubStringRange source(String::cast(script->source()), start, len); |
| 491 for (const auto& c : source) { |
| 492 json_of << AsEscapedUC16ForJSON(c); |
| 493 } |
| 494 } |
| 495 json_of << "\",\n\"phases\":["; |
| 496 fclose(json_file); |
| 497 } |
| 498 |
| 499 return pipeline_statistics; |
| 500 } |
| 501 |
| 502 class PipelineCompilationJob final : public OptimizedCompileJob { |
| 463 public: | 503 public: |
| 464 explicit PipelineCompilationJob(CompilationInfo* info) | 504 explicit PipelineCompilationJob(CompilationInfo* info) |
| 465 : OptimizedCompileJob(info, "TurboFan") {} | 505 : OptimizedCompileJob(info, "TurboFan"), |
| 506 zone_pool_(info->isolate()->allocator()), |
| 507 pipeline_statistics_(CreatePipelineStatistics(info, &zone_pool_)), |
| 508 data_(&zone_pool_, info, pipeline_statistics_.get()), |
| 509 pipeline_(&data_), |
| 510 linkage_(Linkage::ComputeIncoming(info->zone(), info)) {} |
| 466 | 511 |
| 467 protected: | 512 protected: |
| 468 virtual Status CreateGraphImpl(); | 513 Status CreateGraphImpl() final; |
| 469 virtual Status OptimizeGraphImpl(); | 514 Status OptimizeGraphImpl() final; |
| 470 virtual Status GenerateCodeImpl(); | 515 Status GenerateCodeImpl() final; |
| 516 |
| 517 private: |
| 518 ZonePool zone_pool_; |
| 519 base::SmartPointer<PipelineStatistics> pipeline_statistics_; |
| 520 PipelineData data_; |
| 521 Pipeline pipeline_; |
| 522 Linkage linkage_; |
| 471 }; | 523 }; |
| 472 | 524 |
| 473 PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() { | 525 PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() { |
| 474 if (info()->shared_info()->asm_function()) { | 526 if (info()->shared_info()->asm_function()) { |
| 475 if (info()->osr_frame()) info()->MarkAsFrameSpecializing(); | 527 if (info()->osr_frame()) info()->MarkAsFrameSpecializing(); |
| 476 info()->MarkAsFunctionContextSpecializing(); | 528 info()->MarkAsFunctionContextSpecializing(); |
| 477 } else { | 529 } else { |
| 478 if (!FLAG_always_opt) { | 530 if (!FLAG_always_opt) { |
| 479 info()->MarkAsBailoutOnUninitialized(); | 531 info()->MarkAsBailoutOnUninitialized(); |
| 480 } | 532 } |
| 481 if (FLAG_native_context_specialization) { | 533 if (FLAG_native_context_specialization) { |
| 482 info()->MarkAsNativeContextSpecializing(); | 534 info()->MarkAsNativeContextSpecializing(); |
| 483 } | 535 } |
| 484 } | 536 } |
| 485 if (!info()->shared_info()->asm_function() || FLAG_turbo_asm_deoptimization) { | 537 if (!info()->shared_info()->asm_function() || FLAG_turbo_asm_deoptimization) { |
| 486 info()->MarkAsDeoptimizationEnabled(); | 538 info()->MarkAsDeoptimizationEnabled(); |
| 487 } | 539 } |
| 488 if (!info()->shared_info()->HasBytecodeArray()) { | 540 if (!info()->shared_info()->HasBytecodeArray()) { |
| 489 if (!Compiler::EnsureDeoptimizationSupport(info())) return FAILED; | 541 if (!Compiler::EnsureDeoptimizationSupport(info())) return FAILED; |
| 490 } | 542 } |
| 491 | 543 |
| 492 Pipeline pipeline(info()); | 544 if (!pipeline_.CreateGraph()) { |
| 493 pipeline.GenerateCode(); | 545 if (isolate()->has_pending_exception()) return FAILED; // Stack overflowed. |
| 494 if (isolate()->has_pending_exception()) return FAILED; // Stack overflowed. | 546 return AbortOptimization(kGraphBuildingFailed); |
| 495 if (info()->code().is_null()) return AbortOptimization(kGraphBuildingFailed); | 547 } |
| 496 | 548 |
| 497 return SUCCEEDED; | 549 return SUCCEEDED; |
| 498 } | 550 } |
| 499 | 551 |
| 500 PipelineCompilationJob::Status PipelineCompilationJob::OptimizeGraphImpl() { | 552 PipelineCompilationJob::Status PipelineCompilationJob::OptimizeGraphImpl() { |
| 501 // TODO(turbofan): Currently everything is done in the first phase. | 553 if (!pipeline_.OptimizeGraph(&linkage_)) return FAILED; |
| 502 DCHECK(!info()->code().is_null()); | |
| 503 return SUCCEEDED; | 554 return SUCCEEDED; |
| 504 } | 555 } |
| 505 | 556 |
| 506 PipelineCompilationJob::Status PipelineCompilationJob::GenerateCodeImpl() { | 557 PipelineCompilationJob::Status PipelineCompilationJob::GenerateCodeImpl() { |
| 507 // TODO(turbofan): Currently everything is done in the first phase. | 558 Handle<Code> code = pipeline_.GenerateCode(&linkage_); |
| 508 DCHECK(!info()->code().is_null()); | 559 if (code.is_null()) { |
| 509 info()->dependencies()->Commit(info()->code()); | 560 if (info()->bailout_reason() == kNoReason) { |
| 561 return AbortOptimization(kCodeGenerationFailed); |
| 562 } |
| 563 return BAILED_OUT; |
| 564 } |
| 565 info()->dependencies()->Commit(code); |
| 566 info()->SetCode(code); |
| 510 if (info()->is_deoptimization_enabled()) { | 567 if (info()->is_deoptimization_enabled()) { |
| 511 info()->context()->native_context()->AddOptimizedCode(*info()->code()); | 568 info()->context()->native_context()->AddOptimizedCode(*code); |
| 512 RegisterWeakObjectsInOptimizedCode(info()->code()); | 569 RegisterWeakObjectsInOptimizedCode(code); |
| 513 } | 570 } |
| 514 return SUCCEEDED; | 571 return SUCCEEDED; |
| 515 } | 572 } |
| 516 | 573 |
| 574 class PipelineWasmCompilationJob final : public OptimizedCompileJob { |
| 575 public: |
| 576 explicit PipelineWasmCompilationJob(CompilationInfo* info, Graph* graph, |
| 577 CallDescriptor* descriptor, |
| 578 SourcePositionTable* source_positions) |
| 579 : OptimizedCompileJob(info, "TurboFan"), |
| 580 zone_pool_(info->isolate()->allocator()), |
| 581 data_(&zone_pool_, info, graph, source_positions), |
| 582 pipeline_(&data_), |
| 583 linkage_(descriptor) {} |
| 584 |
| 585 protected: |
| 586 Status CreateGraphImpl() final; |
| 587 Status OptimizeGraphImpl() final; |
| 588 Status GenerateCodeImpl() final; |
| 589 |
| 590 private: |
| 591 ZonePool zone_pool_; |
| 592 PipelineData data_; |
| 593 Pipeline pipeline_; |
| 594 Linkage linkage_; |
| 595 }; |
| 596 |
| 597 PipelineWasmCompilationJob::Status |
| 598 PipelineWasmCompilationJob::CreateGraphImpl() { |
| 599 return SUCCEEDED; |
| 600 } |
| 601 |
| 602 PipelineWasmCompilationJob::Status |
| 603 PipelineWasmCompilationJob::OptimizeGraphImpl() { |
| 604 if (!pipeline_.ScheduleAndSelectInstructions(&linkage_)) return FAILED; |
| 605 return SUCCEEDED; |
| 606 } |
| 607 |
| 608 PipelineWasmCompilationJob::Status |
| 609 PipelineWasmCompilationJob::GenerateCodeImpl() { |
| 610 pipeline_.GenerateCode(&linkage_); |
| 611 return SUCCEEDED; |
| 612 } |
| 613 |
| 517 } // namespace | 614 } // namespace |
| 518 | 615 |
| 519 | 616 |
| 520 template <typename Phase> | 617 template <typename Phase> |
| 521 void Pipeline::Run() { | 618 void Pipeline::Run() { |
| 522 PipelineRunScope scope(this->data_, Phase::phase_name()); | 619 PipelineRunScope scope(this->data_, Phase::phase_name()); |
| 523 Phase phase; | 620 Phase phase; |
| 524 phase.Run(this->data_, scope.zone()); | 621 phase.Run(this->data_, scope.zone()); |
| 525 } | 622 } |
| 526 | 623 |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 } | 1230 } |
| 1134 }; | 1231 }; |
| 1135 | 1232 |
| 1136 | 1233 |
| 1137 void Pipeline::BeginPhaseKind(const char* phase_kind_name) { | 1234 void Pipeline::BeginPhaseKind(const char* phase_kind_name) { |
| 1138 if (data_->pipeline_statistics() != nullptr) { | 1235 if (data_->pipeline_statistics() != nullptr) { |
| 1139 data_->pipeline_statistics()->BeginPhaseKind(phase_kind_name); | 1236 data_->pipeline_statistics()->BeginPhaseKind(phase_kind_name); |
| 1140 } | 1237 } |
| 1141 } | 1238 } |
| 1142 | 1239 |
| 1240 void Pipeline::EndPhaseKind() { |
| 1241 if (data_->pipeline_statistics() != nullptr) { |
| 1242 data_->pipeline_statistics()->EndPhaseKind(); |
| 1243 } |
| 1244 } |
| 1143 | 1245 |
| 1144 void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { | 1246 void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { |
| 1145 if (FLAG_trace_turbo) { | 1247 if (FLAG_trace_turbo) { |
| 1146 Run<PrintGraphPhase>(phase); | 1248 Run<PrintGraphPhase>(phase); |
| 1147 } | 1249 } |
| 1148 if (FLAG_turbo_verify) { | 1250 if (FLAG_turbo_verify) { |
| 1149 Run<VerifyGraphPhase>(untyped); | 1251 Run<VerifyGraphPhase>(untyped); |
| 1150 } | 1252 } |
| 1151 } | 1253 } |
| 1152 | 1254 |
| 1153 | 1255 bool Pipeline::CreateGraph() { |
| 1154 Handle<Code> Pipeline::GenerateCode() { | 1256 PipelineData* data = this->data_; |
| 1155 ZonePool zone_pool(isolate()->allocator()); | |
| 1156 base::SmartPointer<PipelineStatistics> pipeline_statistics; | |
| 1157 | |
| 1158 if (FLAG_turbo_stats) { | |
| 1159 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); | |
| 1160 pipeline_statistics->BeginPhaseKind("initializing"); | |
| 1161 } | |
| 1162 | |
| 1163 if (FLAG_trace_turbo) { | |
| 1164 FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "w+"); | |
| 1165 if (json_file != nullptr) { | |
| 1166 OFStream json_of(json_file); | |
| 1167 Handle<Script> script = info()->script(); | |
| 1168 base::SmartArrayPointer<char> function_name = info()->GetDebugName(); | |
| 1169 int pos = info()->shared_info()->start_position(); | |
| 1170 json_of << "{\"function\":\"" << function_name.get() | |
| 1171 << "\", \"sourcePosition\":" << pos << ", \"source\":\""; | |
| 1172 if (!script->IsUndefined() && !script->source()->IsUndefined()) { | |
| 1173 DisallowHeapAllocation no_allocation; | |
| 1174 int start = info()->shared_info()->start_position(); | |
| 1175 int len = info()->shared_info()->end_position() - start; | |
| 1176 String::SubStringRange source(String::cast(script->source()), start, | |
| 1177 len); | |
| 1178 for (const auto& c : source) { | |
| 1179 json_of << AsEscapedUC16ForJSON(c); | |
| 1180 } | |
| 1181 } | |
| 1182 json_of << "\",\n\"phases\":["; | |
| 1183 fclose(json_file); | |
| 1184 } | |
| 1185 } | |
| 1186 | |
| 1187 PipelineData data(&zone_pool, info(), pipeline_statistics.get()); | |
| 1188 this->data_ = &data; | |
| 1189 | 1257 |
| 1190 BeginPhaseKind("graph creation"); | 1258 BeginPhaseKind("graph creation"); |
| 1191 | 1259 |
| 1192 if (FLAG_trace_turbo) { | 1260 if (FLAG_trace_turbo) { |
| 1193 OFStream os(stdout); | 1261 OFStream os(stdout); |
| 1194 os << "---------------------------------------------------\n" | 1262 os << "---------------------------------------------------\n" |
| 1195 << "Begin compiling method " << info()->GetDebugName().get() | 1263 << "Begin compiling method " << info()->GetDebugName().get() |
| 1196 << " using Turbofan" << std::endl; | 1264 << " using Turbofan" << std::endl; |
| 1197 TurboCfgFile tcf(isolate()); | 1265 TurboCfgFile tcf(isolate()); |
| 1198 tcf << AsC1VCompilation(info()); | 1266 tcf << AsC1VCompilation(info()); |
| 1199 } | 1267 } |
| 1200 | 1268 |
| 1201 data.source_positions()->AddDecorator(); | 1269 data->source_positions()->AddDecorator(); |
| 1202 | 1270 |
| 1203 if (FLAG_loop_assignment_analysis) { | 1271 if (FLAG_loop_assignment_analysis) { |
| 1204 Run<LoopAssignmentAnalysisPhase>(); | 1272 Run<LoopAssignmentAnalysisPhase>(); |
| 1205 } | 1273 } |
| 1206 | 1274 |
| 1207 Run<TypeHintAnalysisPhase>(); | 1275 Run<TypeHintAnalysisPhase>(); |
| 1208 | 1276 |
| 1209 Run<GraphBuilderPhase>(); | 1277 Run<GraphBuilderPhase>(); |
| 1210 if (data.compilation_failed()) return Handle<Code>::null(); | 1278 if (data->compilation_failed()) { |
| 1279 EndPhaseKind(); |
| 1280 return false; |
| 1281 } |
| 1211 RunPrintAndVerify("Initial untyped", true); | 1282 RunPrintAndVerify("Initial untyped", true); |
| 1212 | 1283 |
| 1213 // Perform OSR deconstruction. | 1284 // Perform OSR deconstruction. |
| 1214 if (info()->is_osr()) { | 1285 if (info()->is_osr()) { |
| 1215 Run<OsrDeconstructionPhase>(); | 1286 Run<OsrDeconstructionPhase>(); |
| 1216 RunPrintAndVerify("OSR deconstruction", true); | 1287 RunPrintAndVerify("OSR deconstruction", true); |
| 1217 } | 1288 } |
| 1218 | 1289 |
| 1219 // Perform function context specialization and inlining (if enabled). | 1290 // Perform function context specialization and inlining (if enabled). |
| 1220 Run<InliningPhase>(); | 1291 Run<InliningPhase>(); |
| 1221 RunPrintAndVerify("Inlined", true); | 1292 RunPrintAndVerify("Inlined", true); |
| 1222 | 1293 |
| 1223 // Remove dead->live edges from the graph. | 1294 // Remove dead->live edges from the graph. |
| 1224 Run<EarlyGraphTrimmingPhase>(); | 1295 Run<EarlyGraphTrimmingPhase>(); |
| 1225 RunPrintAndVerify("Early trimmed", true); | 1296 RunPrintAndVerify("Early trimmed", true); |
| 1226 | 1297 |
| 1227 if (FLAG_print_turbo_replay) { | 1298 if (FLAG_print_turbo_replay) { |
| 1228 // Print a replay of the initial graph. | 1299 // Print a replay of the initial graph. |
| 1229 GraphReplayPrinter::PrintReplay(data.graph()); | 1300 GraphReplayPrinter::PrintReplay(data->graph()); |
| 1230 } | 1301 } |
| 1231 | 1302 |
| 1232 // Type the graph. | 1303 // Type the graph. |
| 1233 base::SmartPointer<Typer> typer; | 1304 base::SmartPointer<Typer> typer; |
| 1234 typer.Reset(new Typer(isolate(), data.graph(), | 1305 typer.Reset(new Typer(isolate(), data->graph(), |
| 1235 info()->is_deoptimization_enabled() | 1306 info()->is_deoptimization_enabled() |
| 1236 ? Typer::kDeoptimizationEnabled | 1307 ? Typer::kDeoptimizationEnabled |
| 1237 : Typer::kNoFlags, | 1308 : Typer::kNoFlags, |
| 1238 info()->dependencies())); | 1309 info()->dependencies())); |
| 1239 Run<TyperPhase>(typer.get()); | 1310 Run<TyperPhase>(typer.get()); |
| 1240 RunPrintAndVerify("Typed"); | 1311 RunPrintAndVerify("Typed"); |
| 1241 | 1312 |
| 1242 BeginPhaseKind("lowering"); | 1313 BeginPhaseKind("lowering"); |
| 1243 | 1314 |
| 1244 // Lower JSOperators where we can determine types. | 1315 // Lower JSOperators where we can determine types. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1273 if (FLAG_turbo_cf_optimization) { | 1344 if (FLAG_turbo_cf_optimization) { |
| 1274 Run<ControlFlowOptimizationPhase>(); | 1345 Run<ControlFlowOptimizationPhase>(); |
| 1275 RunPrintAndVerify("Control flow optimized"); | 1346 RunPrintAndVerify("Control flow optimized"); |
| 1276 } | 1347 } |
| 1277 | 1348 |
| 1278 // Lower changes that have been inserted before. | 1349 // Lower changes that have been inserted before. |
| 1279 Run<LateOptimizationPhase>(); | 1350 Run<LateOptimizationPhase>(); |
| 1280 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 1351 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
| 1281 RunPrintAndVerify("Late optimized", true); | 1352 RunPrintAndVerify("Late optimized", true); |
| 1282 | 1353 |
| 1354 // Kill the Typer and thereby uninstall the decorator (if any). |
| 1355 typer.Reset(nullptr); |
| 1356 |
| 1357 EndPhaseKind(); |
| 1358 |
| 1359 return true; |
| 1360 } |
| 1361 |
| 1362 bool Pipeline::OptimizeGraph(Linkage* linkage) { |
| 1363 PipelineData* data = this->data_; |
| 1364 |
| 1365 BeginPhaseKind("block building"); |
| 1366 |
| 1283 Run<LateGraphTrimmingPhase>(); | 1367 Run<LateGraphTrimmingPhase>(); |
| 1284 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 1368 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
| 1285 RunPrintAndVerify("Late trimmed", true); | 1369 RunPrintAndVerify("Late trimmed", true); |
| 1286 | 1370 |
| 1287 BeginPhaseKind("block building"); | 1371 data->source_positions()->RemoveDecorator(); |
| 1288 | 1372 |
| 1289 data.source_positions()->RemoveDecorator(); | 1373 return ScheduleAndSelectInstructions(linkage); |
| 1374 } |
| 1290 | 1375 |
| 1291 // Kill the Typer and thereby uninstall the decorator (if any). | 1376 Handle<Code> Pipeline::GenerateCode() { |
| 1292 typer.Reset(nullptr); | 1377 PipelineData* data = this->data_; |
| 1293 | 1378 |
| 1294 return ScheduleAndGenerateCode( | 1379 Linkage linkage(Linkage::ComputeIncoming(data->instruction_zone(), info())); |
| 1295 Linkage::ComputeIncoming(data.instruction_zone(), info())); | 1380 |
| 1381 if (!CreateGraph()) return Handle<Code>::null(); |
| 1382 if (!OptimizeGraph(&linkage)) return Handle<Code>::null(); |
| 1383 return GenerateCode(&linkage); |
| 1296 } | 1384 } |
| 1297 | 1385 |
| 1298 Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate, | 1386 Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate, |
| 1299 CallDescriptor* call_descriptor, | 1387 CallDescriptor* call_descriptor, |
| 1300 Graph* graph, Schedule* schedule, | 1388 Graph* graph, Schedule* schedule, |
| 1301 Code::Flags flags, | 1389 Code::Flags flags, |
| 1302 const char* debug_name) { | 1390 const char* debug_name) { |
| 1303 CompilationInfo info(CStrVector(debug_name), isolate, graph->zone(), flags); | 1391 CompilationInfo info(CStrVector(debug_name), isolate, graph->zone(), flags); |
| 1304 | 1392 |
| 1305 // Construct a pipeline for scheduling and code generation. | 1393 // Construct a pipeline for scheduling and code generation. |
| 1306 ZonePool zone_pool(isolate->allocator()); | 1394 ZonePool zone_pool(isolate->allocator()); |
| 1307 PipelineData data(&zone_pool, &info, graph, schedule); | 1395 PipelineData data(&zone_pool, &info, graph, schedule); |
| 1308 base::SmartPointer<PipelineStatistics> pipeline_statistics; | 1396 base::SmartPointer<PipelineStatistics> pipeline_statistics; |
| 1309 if (FLAG_turbo_stats) { | 1397 if (FLAG_turbo_stats) { |
| 1310 pipeline_statistics.Reset(new PipelineStatistics(&info, &zone_pool)); | 1398 pipeline_statistics.Reset(new PipelineStatistics(&info, &zone_pool)); |
| 1311 pipeline_statistics->BeginPhaseKind("stub codegen"); | 1399 pipeline_statistics->BeginPhaseKind("stub codegen"); |
| 1312 } | 1400 } |
| 1313 | 1401 |
| 1314 Pipeline pipeline(&info); | 1402 Pipeline pipeline(&data); |
| 1315 pipeline.data_ = &data; | |
| 1316 DCHECK_NOT_NULL(data.schedule()); | 1403 DCHECK_NOT_NULL(data.schedule()); |
| 1317 | 1404 |
| 1318 if (FLAG_trace_turbo) { | 1405 if (FLAG_trace_turbo) { |
| 1319 FILE* json_file = OpenVisualizerLogFile(&info, nullptr, "json", "w+"); | 1406 FILE* json_file = OpenVisualizerLogFile(&info, nullptr, "json", "w+"); |
| 1320 if (json_file != nullptr) { | 1407 if (json_file != nullptr) { |
| 1321 OFStream json_of(json_file); | 1408 OFStream json_of(json_file); |
| 1322 json_of << "{\"function\":\"" << info.GetDebugName().get() | 1409 json_of << "{\"function\":\"" << info.GetDebugName().get() |
| 1323 << "\", \"source\":\"\",\n\"phases\":["; | 1410 << "\", \"source\":\"\",\n\"phases\":["; |
| 1324 fclose(json_file); | 1411 fclose(json_file); |
| 1325 } | 1412 } |
| 1326 pipeline.Run<PrintGraphPhase>("Machine"); | 1413 pipeline.Run<PrintGraphPhase>("Machine"); |
| 1327 } | 1414 } |
| 1328 | 1415 |
| 1329 pipeline.Run<VerifyGraphPhase>(false, true); | 1416 pipeline.Run<VerifyGraphPhase>(false, true); |
| 1330 return pipeline.ScheduleAndGenerateCode(call_descriptor); | 1417 return pipeline.ScheduleAndGenerateCode(call_descriptor); |
| 1331 } | 1418 } |
| 1332 | 1419 |
| 1420 // static |
| 1421 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info) { |
| 1422 ZonePool zone_pool(info->isolate()->allocator()); |
| 1423 base::SmartPointer<PipelineStatistics> pipeline_statistics( |
| 1424 CreatePipelineStatistics(info, &zone_pool)); |
| 1425 PipelineData data(&zone_pool, info, pipeline_statistics.get()); |
| 1426 Pipeline pipeline(&data); |
| 1427 return pipeline.GenerateCode(); |
| 1428 } |
| 1333 | 1429 |
| 1430 // static |
| 1334 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, | 1431 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, |
| 1335 Graph* graph, | 1432 Graph* graph, |
| 1336 Schedule* schedule) { | 1433 Schedule* schedule) { |
| 1337 CallDescriptor* call_descriptor = | 1434 CallDescriptor* call_descriptor = |
| 1338 Linkage::ComputeIncoming(info->zone(), info); | 1435 Linkage::ComputeIncoming(info->zone(), info); |
| 1339 return GenerateCodeForTesting(info, call_descriptor, graph, schedule); | 1436 return GenerateCodeForTesting(info, call_descriptor, graph, schedule); |
| 1340 } | 1437 } |
| 1341 | 1438 |
| 1342 | 1439 // static |
| 1343 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, | 1440 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, |
| 1344 CallDescriptor* call_descriptor, | 1441 CallDescriptor* call_descriptor, |
| 1345 Graph* graph, | 1442 Graph* graph, |
| 1346 Schedule* schedule) { | 1443 Schedule* schedule) { |
| 1347 // Construct a pipeline for scheduling and code generation. | 1444 // Construct a pipeline for scheduling and code generation. |
| 1348 ZonePool zone_pool(info->isolate()->allocator()); | 1445 ZonePool zone_pool(info->isolate()->allocator()); |
| 1349 PipelineData data(&zone_pool, info, graph, schedule); | 1446 PipelineData data(&zone_pool, info, graph, schedule); |
| 1350 base::SmartPointer<PipelineStatistics> pipeline_statistics; | 1447 base::SmartPointer<PipelineStatistics> pipeline_statistics; |
| 1351 if (FLAG_turbo_stats) { | 1448 if (FLAG_turbo_stats) { |
| 1352 pipeline_statistics.Reset(new PipelineStatistics(info, &zone_pool)); | 1449 pipeline_statistics.Reset(new PipelineStatistics(info, &zone_pool)); |
| 1353 pipeline_statistics->BeginPhaseKind("test codegen"); | 1450 pipeline_statistics->BeginPhaseKind("test codegen"); |
| 1354 } | 1451 } |
| 1355 | 1452 |
| 1356 Pipeline pipeline(info); | 1453 Pipeline pipeline(&data); |
| 1357 pipeline.data_ = &data; | |
| 1358 if (data.schedule() == nullptr) { | 1454 if (data.schedule() == nullptr) { |
| 1359 // TODO(rossberg): Should this really be untyped? | 1455 // TODO(rossberg): Should this really be untyped? |
| 1360 pipeline.RunPrintAndVerify("Machine", true); | 1456 pipeline.RunPrintAndVerify("Machine", true); |
| 1361 } | 1457 } |
| 1362 | 1458 |
| 1363 return pipeline.ScheduleAndGenerateCode(call_descriptor); | 1459 return pipeline.ScheduleAndGenerateCode(call_descriptor); |
| 1364 } | 1460 } |
| 1365 | 1461 |
| 1366 void Pipeline::InitializeWasmCompilation( | 1462 // static |
| 1367 Zone* pipeline_zone, ZonePool* zone_pool, Graph* graph, | 1463 OptimizedCompileJob* Pipeline::NewCompilationJob(CompilationInfo* info) { |
| 1368 SourcePositionTable* source_positions) { | 1464 return new PipelineCompilationJob(info); |
| 1369 data_ = new (pipeline_zone) | |
| 1370 PipelineData(zone_pool, info(), graph, source_positions); | |
| 1371 RunPrintAndVerify("Machine", true); | |
| 1372 } | 1465 } |
| 1373 | 1466 |
| 1374 bool Pipeline::ExecuteWasmCompilation(CallDescriptor* descriptor) { | 1467 // static |
| 1375 return ScheduleGraph(descriptor); | 1468 OptimizedCompileJob* Pipeline::NewWasmCompilationJob( |
| 1376 } | 1469 CompilationInfo* info, Graph* graph, CallDescriptor* descriptor, |
| 1377 | 1470 SourcePositionTable* source_positions) { |
| 1378 Handle<Code> Pipeline::FinalizeWasmCompilation(CallDescriptor* descriptor) { | 1471 return new PipelineWasmCompilationJob(info, graph, descriptor, |
| 1379 Handle<Code> result = GenerateCode(descriptor); | 1472 source_positions); |
| 1380 data_->Destroy(); | |
| 1381 return result; | |
| 1382 } | |
| 1383 | |
| 1384 OptimizedCompileJob* Pipeline::NewCompilationJob(CompilationInfo* info) { | |
| 1385 return new (info->zone()) PipelineCompilationJob(info); | |
| 1386 } | 1473 } |
| 1387 | 1474 |
| 1388 bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, | 1475 bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, |
| 1389 InstructionSequence* sequence, | 1476 InstructionSequence* sequence, |
| 1390 bool run_verifier) { | 1477 bool run_verifier) { |
| 1391 CompilationInfo info(ArrayVector("testing"), sequence->isolate(), | 1478 CompilationInfo info(ArrayVector("testing"), sequence->isolate(), |
| 1392 sequence->zone()); | 1479 sequence->zone()); |
| 1393 ZonePool zone_pool(sequence->isolate()->allocator()); | 1480 ZonePool zone_pool(sequence->isolate()->allocator()); |
| 1394 PipelineData data(&zone_pool, &info, sequence); | 1481 PipelineData data(&zone_pool, &info, sequence); |
| 1395 Pipeline pipeline(&info); | 1482 Pipeline pipeline(&data); |
| 1396 pipeline.data_ = &data; | |
| 1397 pipeline.data_->InitializeFrameData(nullptr); | 1483 pipeline.data_->InitializeFrameData(nullptr); |
| 1398 pipeline.AllocateRegisters(config, nullptr, run_verifier); | 1484 pipeline.AllocateRegisters(config, nullptr, run_verifier); |
| 1399 return !data.compilation_failed(); | 1485 return !data.compilation_failed(); |
| 1400 } | 1486 } |
| 1401 | 1487 |
| 1402 Handle<Code> Pipeline::ScheduleAndGenerateCode( | 1488 bool Pipeline::ScheduleAndSelectInstructions(Linkage* linkage) { |
| 1403 CallDescriptor* call_descriptor) { | 1489 CallDescriptor* call_descriptor = linkage->GetIncomingDescriptor(); |
| 1404 if (ScheduleGraph(call_descriptor)) { | 1490 PipelineData* data = this->data_; |
| 1405 return GenerateCode(call_descriptor); | |
| 1406 } else { | |
| 1407 return Handle<Code>::null(); | |
| 1408 } | |
| 1409 } | |
| 1410 | 1491 |
| 1411 bool Pipeline::ScheduleGraph(CallDescriptor* call_descriptor) { | |
| 1412 PipelineData* data = this->data_; | |
| 1413 DCHECK_NOT_NULL(data); | |
| 1414 DCHECK_NOT_NULL(data->graph()); | 1492 DCHECK_NOT_NULL(data->graph()); |
| 1415 | 1493 |
| 1416 if (data->schedule() == nullptr) Run<ComputeSchedulePhase>(); | 1494 if (data->schedule() == nullptr) Run<ComputeSchedulePhase>(); |
| 1417 TraceSchedule(data->info(), data->schedule()); | 1495 TraceSchedule(data->info(), data->schedule()); |
| 1418 | 1496 |
| 1419 if (FLAG_turbo_profiling) { | 1497 if (FLAG_turbo_profiling) { |
| 1420 data->set_profiler_data(BasicBlockInstrumentor::Instrument( | 1498 data->set_profiler_data(BasicBlockInstrumentor::Instrument( |
| 1421 info(), data->graph(), data->schedule())); | 1499 info(), data->graph(), data->schedule())); |
| 1422 } | 1500 } |
| 1423 | 1501 |
| 1424 data->InitializeInstructionSequence(call_descriptor); | 1502 data->InitializeInstructionSequence(call_descriptor); |
| 1425 | 1503 |
| 1426 data->InitializeFrameData(call_descriptor); | 1504 data->InitializeFrameData(call_descriptor); |
| 1427 // Select and schedule instructions covering the scheduled graph. | 1505 // Select and schedule instructions covering the scheduled graph. |
| 1428 Linkage linkage(call_descriptor); | 1506 Run<InstructionSelectionPhase>(linkage); |
| 1429 Run<InstructionSelectionPhase>(&linkage); | |
| 1430 | 1507 |
| 1431 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | 1508 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
| 1432 TurboCfgFile tcf(isolate()); | 1509 TurboCfgFile tcf(isolate()); |
| 1433 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), | 1510 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), |
| 1434 data->sequence()); | 1511 data->sequence()); |
| 1435 } | 1512 } |
| 1436 | 1513 |
| 1437 if (FLAG_trace_turbo) { | 1514 if (FLAG_trace_turbo) { |
| 1515 std::ostringstream source_position_output; |
| 1438 // Output source position information before the graph is deleted. | 1516 // Output source position information before the graph is deleted. |
| 1439 data_->source_positions()->Print(*(data->source_position_output())); | 1517 data_->source_positions()->Print(source_position_output); |
| 1518 data_->set_source_position_output(source_position_output.str()); |
| 1440 } | 1519 } |
| 1441 | 1520 |
| 1442 data->DeleteGraphZone(); | 1521 data->DeleteGraphZone(); |
| 1443 | 1522 |
| 1444 BeginPhaseKind("register allocation"); | 1523 BeginPhaseKind("register allocation"); |
| 1445 | 1524 |
| 1446 bool run_verifier = FLAG_turbo_verify_allocation; | 1525 bool run_verifier = FLAG_turbo_verify_allocation; |
| 1447 | 1526 |
| 1448 // Allocate registers. | 1527 // Allocate registers. |
| 1449 AllocateRegisters( | 1528 AllocateRegisters( |
| 1450 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN), | 1529 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN), |
| 1451 call_descriptor, run_verifier); | 1530 call_descriptor, run_verifier); |
| 1452 Run<FrameElisionPhase>(); | 1531 Run<FrameElisionPhase>(); |
| 1453 if (data->compilation_failed()) { | 1532 if (data->compilation_failed()) { |
| 1454 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); | 1533 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
| 1534 EndPhaseKind(); |
| 1455 return false; | 1535 return false; |
| 1456 } | 1536 } |
| 1457 | 1537 |
| 1458 BeginPhaseKind("code generation"); | |
| 1459 // TODO(mtrofin): move this off to the register allocator. | 1538 // TODO(mtrofin): move this off to the register allocator. |
| 1460 bool generate_frame_at_start = | 1539 bool generate_frame_at_start = |
| 1461 data_->sequence()->instruction_blocks().front()->must_construct_frame(); | 1540 data_->sequence()->instruction_blocks().front()->must_construct_frame(); |
| 1462 // Optimimize jumps. | 1541 // Optimimize jumps. |
| 1463 if (FLAG_turbo_jt) { | 1542 if (FLAG_turbo_jt) { |
| 1464 Run<JumpThreadingPhase>(generate_frame_at_start); | 1543 Run<JumpThreadingPhase>(generate_frame_at_start); |
| 1465 } | 1544 } |
| 1545 |
| 1546 EndPhaseKind(); |
| 1547 |
| 1466 return true; | 1548 return true; |
| 1467 } | 1549 } |
| 1468 | 1550 |
| 1469 Handle<Code> Pipeline::GenerateCode(CallDescriptor* call_descriptor) { | 1551 Handle<Code> Pipeline::GenerateCode(Linkage* linkage) { |
| 1470 PipelineData* data = this->data_; | 1552 PipelineData* data = this->data_; |
| 1471 Linkage linkage(call_descriptor); | 1553 |
| 1554 BeginPhaseKind("code generation"); |
| 1555 |
| 1472 // Generate final machine code. | 1556 // Generate final machine code. |
| 1473 Run<GenerateCodePhase>(&linkage); | 1557 Run<GenerateCodePhase>(linkage); |
| 1474 | 1558 |
| 1475 Handle<Code> code = data->code(); | 1559 Handle<Code> code = data->code(); |
| 1476 if (data->profiler_data() != nullptr) { | 1560 if (data->profiler_data()) { |
| 1477 #if ENABLE_DISASSEMBLER | 1561 #if ENABLE_DISASSEMBLER |
| 1478 std::ostringstream os; | 1562 std::ostringstream os; |
| 1479 code->Disassemble(nullptr, os); | 1563 code->Disassemble(nullptr, os); |
| 1480 data->profiler_data()->SetCode(&os); | 1564 data->profiler_data()->SetCode(&os); |
| 1481 #endif | 1565 #endif |
| 1482 } | 1566 } |
| 1483 | 1567 |
| 1484 info()->SetCode(code); | 1568 info()->SetCode(code); |
| 1485 v8::internal::CodeGenerator::PrintCode(code, info()); | 1569 v8::internal::CodeGenerator::PrintCode(code, info()); |
| 1486 | 1570 |
| 1487 if (FLAG_trace_turbo) { | 1571 if (FLAG_trace_turbo) { |
| 1488 FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "a+"); | 1572 FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "a+"); |
| 1489 if (json_file != nullptr) { | 1573 if (json_file != nullptr) { |
| 1490 OFStream json_of(json_file); | 1574 OFStream json_of(json_file); |
| 1491 json_of | 1575 json_of |
| 1492 << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\""; | 1576 << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\""; |
| 1493 #if ENABLE_DISASSEMBLER | 1577 #if ENABLE_DISASSEMBLER |
| 1494 std::stringstream disassembly_stream; | 1578 std::stringstream disassembly_stream; |
| 1495 code->Disassemble(nullptr, disassembly_stream); | 1579 code->Disassemble(nullptr, disassembly_stream); |
| 1496 std::string disassembly_string(disassembly_stream.str()); | 1580 std::string disassembly_string(disassembly_stream.str()); |
| 1497 for (const auto& c : disassembly_string) { | 1581 for (const auto& c : disassembly_string) { |
| 1498 json_of << AsEscapedUC16ForJSON(c); | 1582 json_of << AsEscapedUC16ForJSON(c); |
| 1499 } | 1583 } |
| 1500 #endif // ENABLE_DISASSEMBLER | 1584 #endif // ENABLE_DISASSEMBLER |
| 1501 json_of << "\"}\n],\n"; | 1585 json_of << "\"}\n],\n"; |
| 1502 json_of << "\"nodePositions\":"; | 1586 json_of << "\"nodePositions\":"; |
| 1503 json_of << data->source_position_output()->str(); | 1587 json_of << data->source_position_output(); |
| 1504 json_of << "}"; | 1588 json_of << "}"; |
| 1505 fclose(json_file); | 1589 fclose(json_file); |
| 1506 } | 1590 } |
| 1507 OFStream os(stdout); | 1591 OFStream os(stdout); |
| 1508 os << "---------------------------------------------------\n" | 1592 os << "---------------------------------------------------\n" |
| 1509 << "Finished compiling method " << info()->GetDebugName().get() | 1593 << "Finished compiling method " << info()->GetDebugName().get() |
| 1510 << " using Turbofan" << std::endl; | 1594 << " using Turbofan" << std::endl; |
| 1511 } | 1595 } |
| 1596 |
| 1512 return code; | 1597 return code; |
| 1513 } | 1598 } |
| 1514 | 1599 |
| 1600 Handle<Code> Pipeline::ScheduleAndGenerateCode( |
| 1601 CallDescriptor* call_descriptor) { |
| 1602 Linkage linkage(call_descriptor); |
| 1603 |
| 1604 // Schedule the graph, perform instruction selection and register allocation. |
| 1605 if (!ScheduleAndSelectInstructions(&linkage)) return Handle<Code>(); |
| 1606 |
| 1607 // Generate the final machine code. |
| 1608 return GenerateCode(&linkage); |
| 1609 } |
| 1610 |
| 1515 void Pipeline::AllocateRegisters(const RegisterConfiguration* config, | 1611 void Pipeline::AllocateRegisters(const RegisterConfiguration* config, |
| 1516 CallDescriptor* descriptor, | 1612 CallDescriptor* descriptor, |
| 1517 bool run_verifier) { | 1613 bool run_verifier) { |
| 1518 PipelineData* data = this->data_; | 1614 PipelineData* data = this->data_; |
| 1519 // Don't track usage for this zone in compiler stats. | 1615 // Don't track usage for this zone in compiler stats. |
| 1520 base::SmartPointer<Zone> verifier_zone; | 1616 base::SmartPointer<Zone> verifier_zone; |
| 1521 RegisterAllocatorVerifier* verifier = nullptr; | 1617 RegisterAllocatorVerifier* verifier = nullptr; |
| 1522 if (run_verifier) { | 1618 if (run_verifier) { |
| 1523 verifier_zone.Reset(new Zone(isolate()->allocator())); | 1619 verifier_zone.Reset(new Zone(isolate()->allocator())); |
| 1524 verifier = new (verifier_zone.get()) RegisterAllocatorVerifier( | 1620 verifier = new (verifier_zone.get()) RegisterAllocatorVerifier( |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1596 | 1692 |
| 1597 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | 1693 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
| 1598 TurboCfgFile tcf(data->isolate()); | 1694 TurboCfgFile tcf(data->isolate()); |
| 1599 tcf << AsC1VRegisterAllocationData("CodeGen", | 1695 tcf << AsC1VRegisterAllocationData("CodeGen", |
| 1600 data->register_allocation_data()); | 1696 data->register_allocation_data()); |
| 1601 } | 1697 } |
| 1602 | 1698 |
| 1603 data->DeleteRegisterAllocationZone(); | 1699 data->DeleteRegisterAllocationZone(); |
| 1604 } | 1700 } |
| 1605 | 1701 |
| 1702 CompilationInfo* Pipeline::info() const { return data_->info(); } |
| 1703 |
| 1606 Isolate* Pipeline::isolate() const { return info()->isolate(); } | 1704 Isolate* Pipeline::isolate() const { return info()->isolate(); } |
| 1607 | 1705 |
| 1608 } // namespace compiler | 1706 } // namespace compiler |
| 1609 } // namespace internal | 1707 } // namespace internal |
| 1610 } // namespace v8 | 1708 } // namespace v8 |
| OLD | NEW |