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 3 // found in the LICENSE file. 4 5 #include "src/compiler/pipeline.h" 6 7 #include <fstream> // NOLINT(readability/streams) 8 #include <memory> 9 #include <sstream> 10 11 #include "src/base/adapters.h" 12 #include "src/base/platform/elapsed-timer.h" 13 #include "src/compilation-info.h" 14 #include "src/compiler.h" 15 #include "src/compiler/ast-graph-builder.h" 16 #include "src/compiler/ast-loop-assignment-analyzer.h" 17 #include "src/compiler/basic-block-instrumentor.h" 18 #include "src/compiler/branch-elimination.h" 19 #include "src/compiler/bytecode-graph-builder.h" 20 #include "src/compiler/checkpoint-elimination.h" 21 #include "src/compiler/code-generator.h" 22 #include "src/compiler/common-operator-reducer.h" 23 #include "src/compiler/control-flow-optimizer.h" 24 #include "src/compiler/dead-code-elimination.h" 25 #include "src/compiler/effect-control-linearizer.h" 26 #include "src/compiler/escape-analysis-reducer.h" 27 #include "src/compiler/escape-analysis.h" 28 #include "src/compiler/frame-elider.h" 29 #include "src/compiler/graph-replay.h" 30 #include "src/compiler/graph-trimmer.h" 31 #include "src/compiler/graph-visualizer.h" 32 #include "src/compiler/instruction-selector.h" 33 #include "src/compiler/instruction.h" 34 #include "src/compiler/js-builtin-reducer.h" 35 #include "src/compiler/js-call-reducer.h" 36 #include "src/compiler/js-context-specialization.h" 37 #include "src/compiler/js-create-lowering.h" 38 #include "src/compiler/js-frame-specialization.h" 39 #include "src/compiler/js-generic-lowering.h" 40 #include "src/compiler/js-inlining-heuristic.h" 41 #include "src/compiler/js-intrinsic-lowering.h" 42 #include "src/compiler/js-native-context-specialization.h" 43 #include "src/compiler/js-typed-lowering.h" 44 #include "src/compiler/jump-threading.h" 45 #include "src/compiler/live-range-separator.h" 46 #include "src/compiler/load-elimination.h" 47 #include "src/compiler/loop-analysis.h" 48 #include "src/compiler/loop-peeling.h" 49 #include "src/compiler/loop-variable-optimizer.h" 50 #include "src/compiler/machine-graph-verifier.h" 51 #include "src/compiler/machine-operator-reducer.h" 52 #include "src/compiler/memory-optimizer.h" 53 #include "src/compiler/move-optimizer.h" 54 #include "src/compiler/osr.h" 55 #include "src/compiler/pipeline-statistics.h" 56 #include "src/compiler/redundancy-elimination.h" 57 #include "src/compiler/register-allocator-verifier.h" 58 #include "src/compiler/register-allocator.h" 59 #include "src/compiler/schedule.h" 60 #include "src/compiler/scheduler.h" 61 #include "src/compiler/select-lowering.h" 62 #include "src/compiler/simplified-lowering.h" 63 #include "src/compiler/simplified-operator-reducer.h" 64 #include "src/compiler/simplified-operator.h" 65 #include "src/compiler/store-store-elimination.h" 66 #include "src/compiler/tail-call-optimization.h" 67 #include "src/compiler/typed-optimization.h" 68 #include "src/compiler/typer.h" 69 #include "src/compiler/value-numbering-reducer.h" 70 #include "src/compiler/verifier.h" 71 #include "src/compiler/zone-stats.h" 72 #include "src/isolate-inl.h" 73 #include "src/ostreams.h" 74 #include "src/parsing/parse-info.h" 75 #include "src/register-configuration.h" 76 #include "src/trap-handler/trap-handler.h" 77 #include "src/type-info.h" 78 #include "src/utils.h" 79 80 namespace v8 { 81 namespace internal { 82 namespace compiler { 83 84 class PipelineData { 85 public: 86 // For main entry point. 87 PipelineData(ZoneStats* zone_stats, CompilationInfo* info, 88 PipelineStatistics* pipeline_statistics) 89 : isolate_(info->isolate()), 90 info_(info), 91 debug_name_(info_->GetDebugName()), 92 outer_zone_(info_->zone()), 93 zone_stats_(zone_stats), 94 pipeline_statistics_(pipeline_statistics), 95 graph_zone_scope_(zone_stats_, ZONE_NAME), 96 graph_zone_(graph_zone_scope_.zone()), 97 instruction_zone_scope_(zone_stats_, ZONE_NAME), 98 instruction_zone_(instruction_zone_scope_.zone()), 99 register_allocation_zone_scope_(zone_stats_, ZONE_NAME), 100 register_allocation_zone_(register_allocation_zone_scope_.zone()) { 101 PhaseScope scope(pipeline_statistics, "init pipeline data"); 102 graph_ = new (graph_zone_) Graph(graph_zone_); 103 source_positions_ = new (graph_zone_) SourcePositionTable(graph_); 104 simplified_ = new (graph_zone_) SimplifiedOperatorBuilder(graph_zone_); 105 machine_ = new (graph_zone_) MachineOperatorBuilder( 106 graph_zone_, MachineType::PointerRepresentation(), 107 InstructionSelector::SupportedMachineOperatorFlags(), 108 InstructionSelector::AlignmentRequirements()); 109 common_ = new (graph_zone_) CommonOperatorBuilder(graph_zone_); 110 javascript_ = new (graph_zone_) JSOperatorBuilder(graph_zone_); 111 jsgraph_ = new (graph_zone_) 112 JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_); 113 is_asm_ = info->shared_info()->asm_function(); 114 } 115 116 // For WASM compile entry point. 117 PipelineData(ZoneStats* zone_stats, CompilationInfo* info, JSGraph* jsgraph, 118 SourcePositionTable* source_positions, 119 ZoneVector<trap_handler::ProtectedInstructionData>* 120 protected_instructions) 121 : isolate_(info->isolate()), 122 info_(info), 123 debug_name_(info_->GetDebugName()), 124 zone_stats_(zone_stats), 125 graph_zone_scope_(zone_stats_, ZONE_NAME), 126 graph_(jsgraph->graph()), 127 source_positions_(source_positions), 128 machine_(jsgraph->machine()), 129 common_(jsgraph->common()), 130 javascript_(jsgraph->javascript()), 131 jsgraph_(jsgraph), 132 instruction_zone_scope_(zone_stats_, ZONE_NAME), 133 instruction_zone_(instruction_zone_scope_.zone()), 134 register_allocation_zone_scope_(zone_stats_, ZONE_NAME), 135 register_allocation_zone_(register_allocation_zone_scope_.zone()), 136 protected_instructions_(protected_instructions) { 137 is_asm_ = 138 info->has_shared_info() ? info->shared_info()->asm_function() : false; 139 } 140 141 // For machine graph testing entry point. 142 PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Graph* graph, 143 Schedule* schedule, SourcePositionTable* source_positions) 144 : isolate_(info->isolate()), 145 info_(info), 146 debug_name_(info_->GetDebugName()), 147 zone_stats_(zone_stats), 148 graph_zone_scope_(zone_stats_, ZONE_NAME), 149 graph_(graph), 150 source_positions_(source_positions), 151 schedule_(schedule), 152 instruction_zone_scope_(zone_stats_, ZONE_NAME), 153 instruction_zone_(instruction_zone_scope_.zone()), 154 register_allocation_zone_scope_(zone_stats_, ZONE_NAME), 155 register_allocation_zone_(register_allocation_zone_scope_.zone()) { 156 is_asm_ = false; 157 } 158 // For register allocation testing entry point. 159 PipelineData(ZoneStats* zone_stats, CompilationInfo* info, 160 InstructionSequence* sequence) 161 : isolate_(info->isolate()), 162 info_(info), 163 debug_name_(info_->GetDebugName()), 164 zone_stats_(zone_stats), 165 graph_zone_scope_(zone_stats_, ZONE_NAME), 166 instruction_zone_scope_(zone_stats_, ZONE_NAME), 167 instruction_zone_(sequence->zone()), 168 sequence_(sequence), 169 register_allocation_zone_scope_(zone_stats_, ZONE_NAME), 170 register_allocation_zone_(register_allocation_zone_scope_.zone()) { 171 is_asm_ = 172 info->has_shared_info() ? info->shared_info()->asm_function() : false; 173 } 174 175 ~PipelineData() { 176 DeleteRegisterAllocationZone(); 177 DeleteInstructionZone(); 178 DeleteGraphZone(); 179 } 180 181 Isolate* isolate() const { return isolate_; } 182 CompilationInfo* info() const { return info_; } 183 ZoneStats* zone_stats() const { return zone_stats_; } 184 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } 185 bool compilation_failed() const { return compilation_failed_; } 186 void set_compilation_failed() { compilation_failed_ = true; } 187 188 bool is_asm() const { return is_asm_; } 189 bool verify_graph() const { return verify_graph_; } 190 void set_verify_graph(bool value) { verify_graph_ = value; } 191 192 Handle<Code> code() { return code_; } 193 void set_code(Handle<Code> code) { 194 DCHECK(code_.is_null()); 195 code_ = code; 196 } 197 198 // RawMachineAssembler generally produces graphs which cannot be verified. 199 bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } 200 201 Zone* graph_zone() const { return graph_zone_; } 202 Graph* graph() const { return graph_; } 203 SourcePositionTable* source_positions() const { return source_positions_; } 204 MachineOperatorBuilder* machine() const { return machine_; } 205 CommonOperatorBuilder* common() const { return common_; } 206 JSOperatorBuilder* javascript() const { return javascript_; } 207 JSGraph* jsgraph() const { return jsgraph_; } 208 Handle<Context> native_context() const { 209 return handle(info()->native_context(), isolate()); 210 } 211 Handle<JSGlobalObject> global_object() const { 212 return handle(info()->global_object(), isolate()); 213 } 214 215 LoopAssignmentAnalysis* loop_assignment() const { return loop_assignment_; } 216 void set_loop_assignment(LoopAssignmentAnalysis* loop_assignment) { 217 DCHECK(!loop_assignment_); 218 loop_assignment_ = loop_assignment; 219 } 220 221 Schedule* schedule() const { return schedule_; } 222 void set_schedule(Schedule* schedule) { 223 DCHECK(!schedule_); 224 schedule_ = schedule; 225 } 226 void reset_schedule() { schedule_ = nullptr; } 227 228 Zone* instruction_zone() const { return instruction_zone_; } 229 InstructionSequence* sequence() const { return sequence_; } 230 Frame* frame() const { return frame_; } 231 232 Zone* register_allocation_zone() const { return register_allocation_zone_; } 233 RegisterAllocationData* register_allocation_data() const { 234 return register_allocation_data_; 235 } 236 237 BasicBlockProfiler::Data* profiler_data() const { return profiler_data_; } 238 void set_profiler_data(BasicBlockProfiler::Data* profiler_data) { 239 profiler_data_ = profiler_data; 240 } 241 242 std::string const& source_position_output() const { 243 return source_position_output_; 244 } 245 void set_source_position_output(std::string const& source_position_output) { 246 source_position_output_ = source_position_output; 247 } 248 249 ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions() 250 const { 251 return protected_instructions_; 252 } 253 254 void DeleteGraphZone() { 255 if (graph_zone_ == nullptr) return; 256 graph_zone_scope_.Destroy(); 257 graph_zone_ = nullptr; 258 graph_ = nullptr; 259 source_positions_ = nullptr; 260 loop_assignment_ = nullptr; 261 simplified_ = nullptr; 262 machine_ = nullptr; 263 common_ = nullptr; 264 javascript_ = nullptr; 265 jsgraph_ = nullptr; 266 schedule_ = nullptr; 267 } 268 269 void DeleteInstructionZone() { 270 if (instruction_zone_ == nullptr) return; 271 instruction_zone_scope_.Destroy(); 272 instruction_zone_ = nullptr; 273 sequence_ = nullptr; 274 frame_ = nullptr; 275 } 276 277 void DeleteRegisterAllocationZone() { 278 if (register_allocation_zone_ == nullptr) return; 279 register_allocation_zone_scope_.Destroy(); 280 register_allocation_zone_ = nullptr; 281 register_allocation_data_ = nullptr; 282 } 283 284 void InitializeInstructionSequence(const CallDescriptor* descriptor) { 285 DCHECK(sequence_ == nullptr); 286 InstructionBlocks* instruction_blocks = 287 InstructionSequence::InstructionBlocksFor(instruction_zone(), 288 schedule()); 289 sequence_ = new (instruction_zone()) InstructionSequence( 290 info()->isolate(), instruction_zone(), instruction_blocks); 291 if (descriptor && descriptor->RequiresFrameAsIncoming()) { 292 sequence_->instruction_blocks()[0]->mark_needs_frame(); 293 } else { 294 DCHECK_EQ(0u, descriptor->CalleeSavedFPRegisters()); 295 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters()); 296 } 297 } 298 299 void InitializeFrameData(CallDescriptor* descriptor) { 300 DCHECK(frame_ == nullptr); 301 int fixed_frame_size = 0; 302 if (descriptor != nullptr) { 303 fixed_frame_size = descriptor->CalculateFixedFrameSize(); 304 } 305 frame_ = new (instruction_zone()) Frame(fixed_frame_size); 306 } 307 308 void InitializeRegisterAllocationData(const RegisterConfiguration* config, 309 CallDescriptor* descriptor) { 310 DCHECK(register_allocation_data_ == nullptr); 311 register_allocation_data_ = new (register_allocation_zone()) 312 RegisterAllocationData(config, register_allocation_zone(), frame(), 313 sequence(), debug_name()); 314 } 315 316 void BeginPhaseKind(const char* phase_kind_name) { 317 if (pipeline_statistics() != nullptr) { 318 pipeline_statistics()->BeginPhaseKind(phase_kind_name); 319 } 320 } 321 322 void EndPhaseKind() { 323 if (pipeline_statistics() != nullptr) { 324 pipeline_statistics()->EndPhaseKind(); 325 } 326 } 327 328 const char* debug_name() const { return debug_name_.get(); } 329 330 private: 331 Isolate* const isolate_; 332 CompilationInfo* const info_; 333 std::unique_ptr<char[]> debug_name_; 334 Zone* outer_zone_ = nullptr; 335 ZoneStats* const zone_stats_; 336 PipelineStatistics* pipeline_statistics_ = nullptr; 337 bool compilation_failed_ = false; 338 bool verify_graph_ = false; 339 bool is_asm_ = false; 340 Handle<Code> code_ = Handle<Code>::null(); 341 342 // All objects in the following group of fields are allocated in graph_zone_. 343 // They are all set to nullptr when the graph_zone_ is destroyed. 344 ZoneStats::Scope graph_zone_scope_; 345 Zone* graph_zone_ = nullptr; 346 Graph* graph_ = nullptr; 347 SourcePositionTable* source_positions_ = nullptr; 348 LoopAssignmentAnalysis* loop_assignment_ = nullptr; 349 SimplifiedOperatorBuilder* simplified_ = nullptr; 350 MachineOperatorBuilder* machine_ = nullptr; 351 CommonOperatorBuilder* common_ = nullptr; 352 JSOperatorBuilder* javascript_ = nullptr; 353 JSGraph* jsgraph_ = nullptr; 354 Schedule* schedule_ = nullptr; 355 356 // All objects in the following group of fields are allocated in 357 // instruction_zone_. They are all set to nullptr when the instruction_zone_ 358 // is 359 // destroyed. 360 ZoneStats::Scope instruction_zone_scope_; 361 Zone* instruction_zone_; 362 InstructionSequence* sequence_ = nullptr; 363 Frame* frame_ = nullptr; 364 365 // All objects in the following group of fields are allocated in 366 // register_allocation_zone_. They are all set to nullptr when the zone is 367 // destroyed. 368 ZoneStats::Scope register_allocation_zone_scope_; 369 Zone* register_allocation_zone_; 370 RegisterAllocationData* register_allocation_data_ = nullptr; 371 372 // Basic block profiling support. 373 BasicBlockProfiler::Data* profiler_data_ = nullptr; 374 375 // Source position output for --trace-turbo. 376 std::string source_position_output_; 377 378 ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions_ = 379 nullptr; 380 381 DISALLOW_COPY_AND_ASSIGN(PipelineData); 382 }; 383 384 class PipelineImpl final { 385 public: 386 explicit PipelineImpl(PipelineData* data) : data_(data) {} 387 388 // Helpers for executing pipeline phases. 389 template <typename Phase> 390 void Run(); 391 template <typename Phase, typename Arg0> 392 void Run(Arg0 arg_0); 393 template <typename Phase, typename Arg0, typename Arg1> 394 void Run(Arg0 arg_0, Arg1 arg_1); 395 396 // Run the graph creation and initial optimization passes. 397 bool CreateGraph(); 398 399 // Run the concurrent optimization passes. 400 bool OptimizeGraph(Linkage* linkage); 401 402 // Perform the actual code generation and return handle to a code object. 403 Handle<Code> GenerateCode(Linkage* linkage); 404 405 bool ScheduleAndSelectInstructions(Linkage* linkage, bool trim_graph); 406 void RunPrintAndVerify(const char* phase, bool untyped = false); 407 Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor); 408 void AllocateRegisters(const RegisterConfiguration* config, 409 CallDescriptor* descriptor, bool run_verifier); 410 411 CompilationInfo* info() const; 412 Isolate* isolate() const; 413 414 PipelineData* const data_; 415 }; 416 417 namespace { 418 419 struct TurboCfgFile : public std::ofstream { 420 explicit TurboCfgFile(Isolate* isolate) 421 : std::ofstream(isolate->GetTurboCfgFileName().c_str(), 422 std::ios_base::app) {} 423 }; 424 425 struct TurboJsonFile : public std::ofstream { 426 TurboJsonFile(CompilationInfo* info, std::ios_base::openmode mode) 427 : std::ofstream(GetVisualizerLogFileName(info, nullptr, "json").get(), 428 mode) {} 429 }; 430 431 void TraceSchedule(CompilationInfo* info, Schedule* schedule) { 432 if (FLAG_trace_turbo) { 433 AllowHandleDereference allow_deref; 434 TurboJsonFile json_of(info, std::ios_base::app); 435 json_of << "{\"name\":\"Schedule\",\"type\":\"schedule\",\"data\":\""; 436 std::stringstream schedule_stream; 437 schedule_stream << *schedule; 438 std::string schedule_string(schedule_stream.str()); 439 for (const auto& c : schedule_string) { 440 json_of << AsEscapedUC16ForJSON(c); 441 } 442 json_of << "\"},\n"; 443 } 444 if (FLAG_trace_turbo_graph || FLAG_trace_turbo_scheduler) { 445 AllowHandleDereference allow_deref; 446 CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); 447 OFStream os(tracing_scope.file()); 448 os << "-- Schedule --------------------------------------\n" << *schedule; 449 } 450 } 451 452 453 class SourcePositionWrapper final : public Reducer { 454 public: 455 SourcePositionWrapper(Reducer* reducer, SourcePositionTable* table) 456 : reducer_(reducer), table_(table) {} 457 ~SourcePositionWrapper() final {} 458 459 Reduction Reduce(Node* node) final { 460 SourcePosition const pos = table_->GetSourcePosition(node); 461 SourcePositionTable::Scope position(table_, pos); 462 return reducer_->Reduce(node); 463 } 464 465 void Finalize() final { reducer_->Finalize(); } 466 467 private: 468 Reducer* const reducer_; 469 SourcePositionTable* const table_; 470 471 DISALLOW_COPY_AND_ASSIGN(SourcePositionWrapper); 472 }; 473 474 475 class JSGraphReducer final : public GraphReducer { 476 public: 477 JSGraphReducer(JSGraph* jsgraph, Zone* zone) 478 : GraphReducer(zone, jsgraph->graph(), jsgraph->Dead()) {} 479 ~JSGraphReducer() final {} 480 }; 481 482 483 void AddReducer(PipelineData* data, GraphReducer* graph_reducer, 484 Reducer* reducer) { 485 if (data->info()->is_source_positions_enabled()) { 486 void* const buffer = data->graph_zone()->New(sizeof(SourcePositionWrapper)); 487 SourcePositionWrapper* const wrapper = 488 new (buffer) SourcePositionWrapper(reducer, data->source_positions()); 489 graph_reducer->AddReducer(wrapper); 490 } else { 491 graph_reducer->AddReducer(reducer); 492 } 493 } 494 495 496 class PipelineRunScope { 497 public: 498 PipelineRunScope(PipelineData* data, const char* phase_name) 499 : phase_scope_( 500 phase_name == nullptr ? nullptr : data->pipeline_statistics(), 501 phase_name), 502 zone_scope_(data->zone_stats(), ZONE_NAME) {} 503 504 Zone* zone() { return zone_scope_.zone(); } 505 506 private: 507 PhaseScope phase_scope_; 508 ZoneStats::Scope zone_scope_; 509 }; 510 511 PipelineStatistics* CreatePipelineStatistics(CompilationInfo* info, 512 ZoneStats* zone_stats) { 513 PipelineStatistics* pipeline_statistics = nullptr; 514 515 if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) { 516 pipeline_statistics = new PipelineStatistics(info, zone_stats); 517 pipeline_statistics->BeginPhaseKind("initializing"); 518 } 519 520 if (FLAG_trace_turbo) { 521 TurboJsonFile json_of(info, std::ios_base::trunc); 522 Handle<Script> script = info->script(); 523 std::unique_ptr<char[]> function_name = info->GetDebugName(); 524 int pos = info->shared_info()->start_position(); 525 json_of << "{\"function\":\"" << function_name.get() 526 << "\", \"sourcePosition\":" << pos << ", \"source\":\""; 527 Isolate* isolate = info->isolate(); 528 if (!script->IsUndefined(isolate) && 529 !script->source()->IsUndefined(isolate)) { 530 DisallowHeapAllocation no_allocation; 531 int start = info->shared_info()->start_position(); 532 int len = info->shared_info()->end_position() - start; 533 String::SubStringRange source(String::cast(script->source()), start, len); 534 for (const auto& c : source) { 535 json_of << AsEscapedUC16ForJSON(c); 536 } 537 } 538 json_of << "\",\n\"phases\":["; 539 } 540 541 return pipeline_statistics; 542 } 543 544 } // namespace 545 546 class PipelineCompilationJob final : public CompilationJob { 547 public: 548 PipelineCompilationJob(ParseInfo* parse_info, Handle<JSFunction> function) 549 // Note that the CompilationInfo is not initialized at the time we pass it 550 // to the CompilationJob constructor, but it is not dereferenced there. 551 : CompilationJob(parse_info->isolate(), &info_, "TurboFan"), 552 parse_info_(parse_info), 553 zone_stats_(parse_info->isolate()->allocator()), 554 info_(parse_info_.get()->zone(), parse_info_.get(), function), 555 pipeline_statistics_(CreatePipelineStatistics(info(), &zone_stats_)), 556 data_(&zone_stats_, info(), pipeline_statistics_.get()), 557 pipeline_(&data_), 558 linkage_(nullptr) {} 559 560 protected: 561 Status PrepareJobImpl() final; 562 Status ExecuteJobImpl() final; 563 Status FinalizeJobImpl() final; 564 565 private: 566 std::unique_ptr<ParseInfo> parse_info_; 567 ZoneStats zone_stats_; 568 CompilationInfo info_; 569 std::unique_ptr<PipelineStatistics> pipeline_statistics_; 570 PipelineData data_; 571 PipelineImpl pipeline_; 572 Linkage* linkage_; 573 574 DISALLOW_COPY_AND_ASSIGN(PipelineCompilationJob); 575 }; 576 577 PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() { 578 if (info()->shared_info()->asm_function()) { 579 if (info()->osr_frame() && !info()->is_optimizing_from_bytecode()) { 580 info()->MarkAsFrameSpecializing(); 581 } 582 info()->MarkAsFunctionContextSpecializing(); 583 } else { 584 if (!FLAG_always_opt) { 585 info()->MarkAsBailoutOnUninitialized(); 586 } 587 if (FLAG_turbo_loop_peeling) { 588 info()->MarkAsLoopPeelingEnabled(); 589 } 590 } 591 if (info()->is_optimizing_from_bytecode() || 592 !info()->shared_info()->asm_function()) { 593 info()->MarkAsDeoptimizationEnabled(); 594 if (FLAG_inline_accessors) { 595 info()->MarkAsAccessorInliningEnabled(); 596 } 597 if (info()->closure()->feedback_vector_cell()->map() == 598 isolate()->heap()->one_closure_cell_map()) { 599 info()->MarkAsFunctionContextSpecializing(); 600 } 601 } 602 if (!info()->is_optimizing_from_bytecode()) { 603 if (!Compiler::EnsureDeoptimizationSupport(info())) return FAILED; 604 } else if (FLAG_turbo_inlining) { 605 info()->MarkAsInliningEnabled(); 606 } 607 608 linkage_ = new (info()->zone()) 609 Linkage(Linkage::ComputeIncoming(info()->zone(), info())); 610 611 if (!pipeline_.CreateGraph()) { 612 if (isolate()->has_pending_exception()) return FAILED; // Stack overflowed. 613 return AbortOptimization(kGraphBuildingFailed); 614 } 615 616 return SUCCEEDED; 617 } 618 619 PipelineCompilationJob::Status PipelineCompilationJob::ExecuteJobImpl() { 620 if (!pipeline_.OptimizeGraph(linkage_)) return FAILED; 621 return SUCCEEDED; 622 } 623 624 PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl() { 625 Handle<Code> code = pipeline_.GenerateCode(linkage_); 626 if (code.is_null()) { 627 if (info()->bailout_reason() == kNoReason) { 628 return AbortOptimization(kCodeGenerationFailed); 629 } 630 return FAILED; 631 } 632 info()->dependencies()->Commit(code); 633 info()->SetCode(code); 634 if (info()->is_deoptimization_enabled()) { 635 info()->context()->native_context()->AddOptimizedCode(*code); 636 RegisterWeakObjectsInOptimizedCode(code); 637 } 638 return SUCCEEDED; 639 } 640 641 class PipelineWasmCompilationJob final : public CompilationJob { 642 public: 643 explicit PipelineWasmCompilationJob( 644 CompilationInfo* info, JSGraph* jsgraph, CallDescriptor* descriptor, 645 SourcePositionTable* source_positions, 646 ZoneVector<trap_handler::ProtectedInstructionData>* protected_insts, 647 bool allow_signalling_nan) 648 : CompilationJob(info->isolate(), info, "TurboFan", 649 State::kReadyToExecute), 650 zone_stats_(info->isolate()->allocator()), 651 data_(&zone_stats_, info, jsgraph, source_positions, protected_insts), 652 pipeline_(&data_), 653 linkage_(descriptor), 654 allow_signalling_nan_(allow_signalling_nan) {} 655 656 protected: 657 Status PrepareJobImpl() final; 658 Status ExecuteJobImpl() final; 659 Status FinalizeJobImpl() final; 660 661 private: 662 ZoneStats zone_stats_; 663 PipelineData data_; 664 PipelineImpl pipeline_; 665 Linkage linkage_; 666 bool allow_signalling_nan_; 667 }; 668 669 PipelineWasmCompilationJob::Status 670 PipelineWasmCompilationJob::PrepareJobImpl() { 671 UNREACHABLE(); // Prepare should always be skipped for WasmCompilationJob. 672 return SUCCEEDED; 673 } 674 675 PipelineWasmCompilationJob::Status 676 PipelineWasmCompilationJob::ExecuteJobImpl() { 677 if (FLAG_trace_turbo) { 678 TurboJsonFile json_of(info(), std::ios_base::trunc); 679 json_of << "{\"function\":\"" << info()->GetDebugName().get() 680 << "\", \"source\":\"\",\n\"phases\":["; 681 } 682 683 pipeline_.RunPrintAndVerify("Machine", true); 684 if (FLAG_wasm_opt) { 685 PipelineData* data = &data_; 686 PipelineRunScope scope(data, "WASM optimization"); 687 JSGraphReducer graph_reducer(data->jsgraph(), scope.zone()); 688 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), 689 data->common()); 690 ValueNumberingReducer value_numbering(scope.zone(), data->graph()->zone()); 691 MachineOperatorReducer machine_reducer(data->jsgraph(), 692 allow_signalling_nan_); 693 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), 694 data->common(), data->machine()); 695 AddReducer(data, &graph_reducer, &dead_code_elimination); 696 AddReducer(data, &graph_reducer, &value_numbering); 697 AddReducer(data, &graph_reducer, &machine_reducer); 698 AddReducer(data, &graph_reducer, &common_reducer); 699 graph_reducer.ReduceGraph(); 700 pipeline_.RunPrintAndVerify("Optimized Machine", true); 701 } 702 703 if (!pipeline_.ScheduleAndSelectInstructions(&linkage_, true)) return FAILED; 704 return SUCCEEDED; 705 } 706 707 PipelineWasmCompilationJob::Status 708 PipelineWasmCompilationJob::FinalizeJobImpl() { 709 pipeline_.GenerateCode(&linkage_); 710 return SUCCEEDED; 711 } 712 713 template <typename Phase> 714 void PipelineImpl::Run() { 715 PipelineRunScope scope(this->data_, Phase::phase_name()); 716 Phase phase; 717 phase.Run(this->data_, scope.zone()); 718 } 719 720 template <typename Phase, typename Arg0> 721 void PipelineImpl::Run(Arg0 arg_0) { 722 PipelineRunScope scope(this->data_, Phase::phase_name()); 723 Phase phase; 724 phase.Run(this->data_, scope.zone(), arg_0); 725 } 726 727 template <typename Phase, typename Arg0, typename Arg1> 728 void PipelineImpl::Run(Arg0 arg_0, Arg1 arg_1) { 729 PipelineRunScope scope(this->data_, Phase::phase_name()); 730 Phase phase; 731 phase.Run(this->data_, scope.zone(), arg_0, arg_1); 732 } 733 734 struct LoopAssignmentAnalysisPhase { 735 static const char* phase_name() { return "loop assignment analysis"; } 736 737 void Run(PipelineData* data, Zone* temp_zone) { 738 if (!data->info()->is_optimizing_from_bytecode()) { 739 AstLoopAssignmentAnalyzer analyzer(data->graph_zone(), data->info()); 740 LoopAssignmentAnalysis* loop_assignment = analyzer.Analyze(); 741 data->set_loop_assignment(loop_assignment); 742 } 743 } 744 }; 745 746 747 struct GraphBuilderPhase { 748 static const char* phase_name() { return "graph builder"; } 749 750 void Run(PipelineData* data, Zone* temp_zone) { 751 bool succeeded = false; 752 753 if (data->info()->is_optimizing_from_bytecode()) { 754 // Bytecode graph builder assumes deoptimziation is enabled. 755 DCHECK(data->info()->is_deoptimization_enabled()); 756 BytecodeGraphBuilder graph_builder( 757 temp_zone, data->info()->shared_info(), 758 handle(data->info()->closure()->feedback_vector()), 759 data->info()->osr_ast_id(), data->jsgraph(), 1.0f, 760 data->source_positions()); 761 succeeded = graph_builder.CreateGraph(); 762 } else { 763 AstGraphBuilderWithPositions graph_builder( 764 temp_zone, data->info(), data->jsgraph(), 1.0f, 765 data->loop_assignment(), data->source_positions()); 766 succeeded = graph_builder.CreateGraph(); 767 } 768 769 if (!succeeded) { 770 data->set_compilation_failed(); 771 } 772 } 773 }; 774 775 776 struct InliningPhase { 777 static const char* phase_name() { return "inlining"; } 778 779 void Run(PipelineData* data, Zone* temp_zone) { 780 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 781 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), 782 data->common()); 783 CheckpointElimination checkpoint_elimination(&graph_reducer); 784 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), 785 data->common(), data->machine()); 786 JSCallReducer::Flags call_reducer_flags = JSCallReducer::kNoFlags; 787 if (data->info()->is_deoptimization_enabled()) { 788 call_reducer_flags |= JSCallReducer::kDeoptimizationEnabled; 789 } 790 JSCallReducer call_reducer(&graph_reducer, data->jsgraph(), 791 call_reducer_flags, data->native_context(), 792 data->info()->dependencies()); 793 JSContextSpecialization context_specialization( 794 &graph_reducer, data->jsgraph(), 795 data->info()->is_function_context_specializing() 796 ? handle(data->info()->context()) 797 : MaybeHandle<Context>()); 798 JSFrameSpecialization frame_specialization( 799 &graph_reducer, data->info()->osr_frame(), data->jsgraph()); 800 JSNativeContextSpecialization::Flags flags = 801 JSNativeContextSpecialization::kNoFlags; 802 if (data->info()->is_accessor_inlining_enabled()) { 803 flags |= JSNativeContextSpecialization::kAccessorInliningEnabled; 804 } 805 if (data->info()->is_bailout_on_uninitialized()) { 806 flags |= JSNativeContextSpecialization::kBailoutOnUninitialized; 807 } 808 if (data->info()->is_deoptimization_enabled()) { 809 flags |= JSNativeContextSpecialization::kDeoptimizationEnabled; 810 } 811 JSNativeContextSpecialization native_context_specialization( 812 &graph_reducer, data->jsgraph(), flags, data->native_context(), 813 data->info()->dependencies(), temp_zone); 814 JSInliningHeuristic inlining( 815 &graph_reducer, data->info()->is_inlining_enabled() 816 ? JSInliningHeuristic::kGeneralInlining 817 : JSInliningHeuristic::kRestrictedInlining, 818 temp_zone, data->info(), data->jsgraph(), data->source_positions()); 819 JSIntrinsicLowering intrinsic_lowering( 820 &graph_reducer, data->jsgraph(), 821 data->info()->is_deoptimization_enabled() 822 ? JSIntrinsicLowering::kDeoptimizationEnabled 823 : JSIntrinsicLowering::kDeoptimizationDisabled); 824 AddReducer(data, &graph_reducer, &dead_code_elimination); 825 AddReducer(data, &graph_reducer, &checkpoint_elimination); 826 AddReducer(data, &graph_reducer, &common_reducer); 827 if (data->info()->is_frame_specializing()) { 828 AddReducer(data, &graph_reducer, &frame_specialization); 829 } 830 AddReducer(data, &graph_reducer, &native_context_specialization); 831 AddReducer(data, &graph_reducer, &context_specialization); 832 AddReducer(data, &graph_reducer, &intrinsic_lowering); 833 AddReducer(data, &graph_reducer, &call_reducer); 834 AddReducer(data, &graph_reducer, &inlining); 835 graph_reducer.ReduceGraph(); 836 } 837 }; 838 839 840 struct TyperPhase { 841 static const char* phase_name() { return "typer"; } 842 843 void Run(PipelineData* data, Zone* temp_zone, Typer* typer) { 844 NodeVector roots(temp_zone); 845 data->jsgraph()->GetCachedNodes(&roots); 846 LoopVariableOptimizer induction_vars(data->jsgraph()->graph(), 847 data->common(), temp_zone); 848 if (FLAG_turbo_loop_variable) induction_vars.Run(); 849 typer->Run(roots, &induction_vars); 850 } 851 }; 852 853 struct UntyperPhase { 854 static const char* phase_name() { return "untyper"; } 855 856 void Run(PipelineData* data, Zone* temp_zone) { 857 class RemoveTypeReducer final : public Reducer { 858 public: 859 Reduction Reduce(Node* node) final { 860 if (NodeProperties::IsTyped(node)) { 861 NodeProperties::RemoveType(node); 862 return Changed(node); 863 } 864 return NoChange(); 865 } 866 }; 867 868 NodeVector roots(temp_zone); 869 data->jsgraph()->GetCachedNodes(&roots); 870 for (Node* node : roots) { 871 NodeProperties::RemoveType(node); 872 } 873 874 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 875 RemoveTypeReducer remove_type_reducer; 876 AddReducer(data, &graph_reducer, &remove_type_reducer); 877 graph_reducer.ReduceGraph(); 878 } 879 }; 880 881 struct OsrDeconstructionPhase { 882 static const char* phase_name() { return "OSR deconstruction"; } 883 884 void Run(PipelineData* data, Zone* temp_zone) { 885 GraphTrimmer trimmer(temp_zone, data->graph()); 886 NodeVector roots(temp_zone); 887 data->jsgraph()->GetCachedNodes(&roots); 888 trimmer.TrimGraph(roots.begin(), roots.end()); 889 890 OsrHelper osr_helper(data->info()); 891 osr_helper.Deconstruct(data->jsgraph(), data->common(), temp_zone); 892 } 893 }; 894 895 896 struct TypedLoweringPhase { 897 static const char* phase_name() { return "typed lowering"; } 898 899 void Run(PipelineData* data, Zone* temp_zone) { 900 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 901 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), 902 data->common()); 903 JSBuiltinReducer builtin_reducer( 904 &graph_reducer, data->jsgraph(), 905 data->info()->is_deoptimization_enabled() 906 ? JSBuiltinReducer::kDeoptimizationEnabled 907 : JSBuiltinReducer::kNoFlags, 908 data->info()->dependencies(), data->native_context()); 909 Handle<FeedbackVector> feedback_vector( 910 data->info()->closure()->feedback_vector()); 911 JSCreateLowering create_lowering( 912 &graph_reducer, data->info()->dependencies(), data->jsgraph(), 913 feedback_vector, data->native_context(), temp_zone); 914 JSTypedLowering::Flags typed_lowering_flags = JSTypedLowering::kNoFlags; 915 if (data->info()->is_deoptimization_enabled()) { 916 typed_lowering_flags |= JSTypedLowering::kDeoptimizationEnabled; 917 } 918 JSTypedLowering typed_lowering(&graph_reducer, data->info()->dependencies(), 919 typed_lowering_flags, data->jsgraph(), 920 temp_zone); 921 TypedOptimization typed_optimization( 922 &graph_reducer, data->info()->dependencies(), 923 data->info()->is_deoptimization_enabled() 924 ? TypedOptimization::kDeoptimizationEnabled 925 : TypedOptimization::kNoFlags, 926 data->jsgraph()); 927 SimplifiedOperatorReducer simple_reducer(&graph_reducer, data->jsgraph()); 928 CheckpointElimination checkpoint_elimination(&graph_reducer); 929 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), 930 data->common(), data->machine()); 931 AddReducer(data, &graph_reducer, &dead_code_elimination); 932 AddReducer(data, &graph_reducer, &builtin_reducer); 933 if (data->info()->is_deoptimization_enabled()) { 934 AddReducer(data, &graph_reducer, &create_lowering); 935 } 936 AddReducer(data, &graph_reducer, &typed_optimization); 937 AddReducer(data, &graph_reducer, &typed_lowering); 938 AddReducer(data, &graph_reducer, &simple_reducer); 939 AddReducer(data, &graph_reducer, &checkpoint_elimination); 940 AddReducer(data, &graph_reducer, &common_reducer); 941 graph_reducer.ReduceGraph(); 942 } 943 }; 944 945 946 struct EscapeAnalysisPhase { 947 static const char* phase_name() { return "escape analysis"; } 948 949 void Run(PipelineData* data, Zone* temp_zone) { 950 EscapeAnalysis escape_analysis(data->graph(), data->jsgraph()->common(), 951 temp_zone); 952 if (!escape_analysis.Run()) return; 953 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 954 EscapeAnalysisReducer escape_reducer(&graph_reducer, data->jsgraph(), 955 &escape_analysis, temp_zone); 956 AddReducer(data, &graph_reducer, &escape_reducer); 957 graph_reducer.ReduceGraph(); 958 if (escape_reducer.compilation_failed()) { 959 data->set_compilation_failed(); 960 return; 961 } 962 escape_reducer.VerifyReplacement(); 963 } 964 }; 965 966 struct SimplifiedLoweringPhase { 967 static const char* phase_name() { return "simplified lowering"; } 968 969 void Run(PipelineData* data, Zone* temp_zone) { 970 SimplifiedLowering lowering(data->jsgraph(), temp_zone, 971 data->source_positions()); 972 lowering.LowerAllNodes(); 973 } 974 }; 975 976 struct LoopPeelingPhase { 977 static const char* phase_name() { return "loop peeling"; } 978 979 void Run(PipelineData* data, Zone* temp_zone) { 980 GraphTrimmer trimmer(temp_zone, data->graph()); 981 NodeVector roots(temp_zone); 982 data->jsgraph()->GetCachedNodes(&roots); 983 trimmer.TrimGraph(roots.begin(), roots.end()); 984 985 LoopTree* loop_tree = 986 LoopFinder::BuildLoopTree(data->jsgraph()->graph(), temp_zone); 987 LoopPeeler::PeelInnerLoopsOfTree(data->graph(), data->common(), loop_tree, 988 temp_zone); 989 } 990 }; 991 992 struct LoopExitEliminationPhase { 993 static const char* phase_name() { return "loop exit elimination"; } 994 995 void Run(PipelineData* data, Zone* temp_zone) { 996 LoopPeeler::EliminateLoopExits(data->graph(), temp_zone); 997 } 998 }; 999 1000 struct ConcurrentOptimizationPrepPhase { 1001 static const char* phase_name() { 1002 return "concurrent optimization preparation"; 1003 } 1004 1005 void Run(PipelineData* data, Zone* temp_zone) { 1006 // Make sure we cache these code stubs. 1007 data->jsgraph()->CEntryStubConstant(1); 1008 data->jsgraph()->CEntryStubConstant(2); 1009 data->jsgraph()->CEntryStubConstant(3); 1010 1011 // This is needed for escape analysis. 1012 NodeProperties::SetType(data->jsgraph()->FalseConstant(), Type::Boolean()); 1013 NodeProperties::SetType(data->jsgraph()->TrueConstant(), Type::Boolean()); 1014 } 1015 }; 1016 1017 struct GenericLoweringPhase { 1018 static const char* phase_name() { return "generic lowering"; } 1019 1020 void Run(PipelineData* data, Zone* temp_zone) { 1021 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 1022 JSGenericLowering generic_lowering(data->jsgraph()); 1023 AddReducer(data, &graph_reducer, &generic_lowering); 1024 graph_reducer.ReduceGraph(); 1025 } 1026 }; 1027 1028 struct EarlyOptimizationPhase { 1029 static const char* phase_name() { return "early optimization"; } 1030 1031 void Run(PipelineData* data, Zone* temp_zone) { 1032 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 1033 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), 1034 data->common()); 1035 SimplifiedOperatorReducer simple_reducer(&graph_reducer, data->jsgraph()); 1036 RedundancyElimination redundancy_elimination(&graph_reducer, temp_zone); 1037 ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone()); 1038 MachineOperatorReducer machine_reducer(data->jsgraph()); 1039 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), 1040 data->common(), data->machine()); 1041 AddReducer(data, &graph_reducer, &dead_code_elimination); 1042 AddReducer(data, &graph_reducer, &simple_reducer); 1043 AddReducer(data, &graph_reducer, &redundancy_elimination); 1044 AddReducer(data, &graph_reducer, &value_numbering); 1045 AddReducer(data, &graph_reducer, &machine_reducer); 1046 AddReducer(data, &graph_reducer, &common_reducer); 1047 graph_reducer.ReduceGraph(); 1048 } 1049 }; 1050 1051 struct ControlFlowOptimizationPhase { 1052 static const char* phase_name() { return "control flow optimization"; } 1053 1054 void Run(PipelineData* data, Zone* temp_zone) { 1055 ControlFlowOptimizer optimizer(data->graph(), data->common(), 1056 data->machine(), temp_zone); 1057 optimizer.Optimize(); 1058 } 1059 }; 1060 1061 struct EffectControlLinearizationPhase { 1062 static const char* phase_name() { return "effect linearization"; } 1063 1064 void Run(PipelineData* data, Zone* temp_zone) { 1065 // The scheduler requires the graphs to be trimmed, so trim now. 1066 // TODO(jarin) Remove the trimming once the scheduler can handle untrimmed 1067 // graphs. 1068 GraphTrimmer trimmer(temp_zone, data->graph()); 1069 NodeVector roots(temp_zone); 1070 data->jsgraph()->GetCachedNodes(&roots); 1071 trimmer.TrimGraph(roots.begin(), roots.end()); 1072 1073 // Schedule the graph without node splitting so that we can 1074 // fix the effect and control flow for nodes with low-level side 1075 // effects (such as changing representation to tagged or 1076 // 'floating' allocation regions.) 1077 Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph(), 1078 Scheduler::kNoFlags); 1079 if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule); 1080 TraceSchedule(data->info(), schedule); 1081 1082 // Post-pass for wiring the control/effects 1083 // - connect allocating representation changes into the control&effect 1084 // chains and lower them, 1085 // - get rid of the region markers, 1086 // - introduce effect phis and rewire effects to get SSA again. 1087 EffectControlLinearizer linearizer(data->jsgraph(), schedule, temp_zone, 1088 data->source_positions()); 1089 linearizer.Run(); 1090 } 1091 }; 1092 1093 // The store-store elimination greatly benefits from doing a common operator 1094 // reducer and dead code elimination just before it, to eliminate conditional 1095 // deopts with a constant condition. 1096 1097 struct DeadCodeEliminationPhase { 1098 static const char* phase_name() { return "dead code elimination"; } 1099 1100 void Run(PipelineData* data, Zone* temp_zone) { 1101 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 1102 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), 1103 data->common()); 1104 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), 1105 data->common(), data->machine()); 1106 AddReducer(data, &graph_reducer, &dead_code_elimination); 1107 AddReducer(data, &graph_reducer, &common_reducer); 1108 graph_reducer.ReduceGraph(); 1109 } 1110 }; 1111 1112 struct StoreStoreEliminationPhase { 1113 static const char* phase_name() { return "store-store elimination"; } 1114 1115 void Run(PipelineData* data, Zone* temp_zone) { 1116 GraphTrimmer trimmer(temp_zone, data->graph()); 1117 NodeVector roots(temp_zone); 1118 data->jsgraph()->GetCachedNodes(&roots); 1119 trimmer.TrimGraph(roots.begin(), roots.end()); 1120 1121 StoreStoreElimination::Run(data->jsgraph(), temp_zone); 1122 } 1123 }; 1124 1125 struct LoadEliminationPhase { 1126 static const char* phase_name() { return "load elimination"; } 1127 1128 void Run(PipelineData* data, Zone* temp_zone) { 1129 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 1130 BranchElimination branch_condition_elimination(&graph_reducer, 1131 data->jsgraph(), temp_zone); 1132 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), 1133 data->common()); 1134 RedundancyElimination redundancy_elimination(&graph_reducer, temp_zone); 1135 LoadElimination load_elimination(&graph_reducer, data->jsgraph(), 1136 temp_zone); 1137 ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone()); 1138 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), 1139 data->common(), data->machine()); 1140 AddReducer(data, &graph_reducer, &branch_condition_elimination); 1141 AddReducer(data, &graph_reducer, &dead_code_elimination); 1142 AddReducer(data, &graph_reducer, &redundancy_elimination); 1143 AddReducer(data, &graph_reducer, &load_elimination); 1144 AddReducer(data, &graph_reducer, &value_numbering); 1145 AddReducer(data, &graph_reducer, &common_reducer); 1146 graph_reducer.ReduceGraph(); 1147 } 1148 }; 1149 1150 struct MemoryOptimizationPhase { 1151 static const char* phase_name() { return "memory optimization"; } 1152 1153 void Run(PipelineData* data, Zone* temp_zone) { 1154 // The memory optimizer requires the graphs to be trimmed, so trim now. 1155 GraphTrimmer trimmer(temp_zone, data->graph()); 1156 NodeVector roots(temp_zone); 1157 data->jsgraph()->GetCachedNodes(&roots); 1158 trimmer.TrimGraph(roots.begin(), roots.end()); 1159 1160 // Optimize allocations and load/store operations. 1161 MemoryOptimizer optimizer(data->jsgraph(), temp_zone); 1162 optimizer.Optimize(); 1163 } 1164 }; 1165 1166 struct LateOptimizationPhase { 1167 static const char* phase_name() { return "late optimization"; } 1168 1169 void Run(PipelineData* data, Zone* temp_zone) { 1170 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); 1171 BranchElimination branch_condition_elimination(&graph_reducer, 1172 data->jsgraph(), temp_zone); 1173 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), 1174 data->common()); 1175 ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone()); 1176 MachineOperatorReducer machine_reducer(data->jsgraph()); 1177 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), 1178 data->common(), data->machine()); 1179 SelectLowering select_lowering(data->jsgraph()->graph(), 1180 data->jsgraph()->common()); 1181 TailCallOptimization tco(data->common(), data->graph()); 1182 AddReducer(data, &graph_reducer, &branch_condition_elimination); 1183 AddReducer(data, &graph_reducer, &dead_code_elimination); 1184 AddReducer(data, &graph_reducer, &value_numbering); 1185 AddReducer(data, &graph_reducer, &machine_reducer); 1186 AddReducer(data, &graph_reducer, &common_reducer); 1187 AddReducer(data, &graph_reducer, &select_lowering); 1188 AddReducer(data, &graph_reducer, &tco); 1189 graph_reducer.ReduceGraph(); 1190 } 1191 }; 1192 1193 struct EarlyGraphTrimmingPhase { 1194 static const char* phase_name() { return "early graph trimming"; } 1195 void Run(PipelineData* data, Zone* temp_zone) { 1196 GraphTrimmer trimmer(temp_zone, data->graph()); 1197 NodeVector roots(temp_zone); 1198 data->jsgraph()->GetCachedNodes(&roots); 1199 trimmer.TrimGraph(roots.begin(), roots.end()); 1200 } 1201 }; 1202 1203 1204 struct LateGraphTrimmingPhase { 1205 static const char* phase_name() { return "late graph trimming"; } 1206 void Run(PipelineData* data, Zone* temp_zone) { 1207 GraphTrimmer trimmer(temp_zone, data->graph()); 1208 NodeVector roots(temp_zone); 1209 if (data->jsgraph()) { 1210 data->jsgraph()->GetCachedNodes(&roots); 1211 } 1212 trimmer.TrimGraph(roots.begin(), roots.end()); 1213 } 1214 }; 1215 1216 1217 struct ComputeSchedulePhase { 1218 static const char* phase_name() { return "scheduling"; } 1219 1220 void Run(PipelineData* data, Zone* temp_zone) { 1221 Schedule* schedule = Scheduler::ComputeSchedule( 1222 temp_zone, data->graph(), data->info()->is_splitting_enabled() 1223 ? Scheduler::kSplitNodes 1224 : Scheduler::kNoFlags); 1225 if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule); 1226 data->set_schedule(schedule); 1227 } 1228 }; 1229 1230 1231 struct InstructionSelectionPhase { 1232 static const char* phase_name() { return "select instructions"; } 1233 1234 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { 1235 InstructionSelector selector( 1236 temp_zone, data->graph()->NodeCount(), linkage, data->sequence(), 1237 data->schedule(), data->source_positions(), data->frame(), 1238 data->info()->is_source_positions_enabled() 1239 ? InstructionSelector::kAllSourcePositions 1240 : InstructionSelector::kCallSourcePositions, 1241 InstructionSelector::SupportedFeatures(), 1242 FLAG_turbo_instruction_scheduling 1243 ? InstructionSelector::kEnableScheduling 1244 : InstructionSelector::kDisableScheduling, 1245 data->info()->will_serialize() 1246 ? InstructionSelector::kEnableSerialization 1247 : InstructionSelector::kDisableSerialization); 1248 if (!selector.SelectInstructions()) { 1249 data->set_compilation_failed(); 1250 } 1251 } 1252 }; 1253 1254 1255 struct MeetRegisterConstraintsPhase { 1256 static const char* phase_name() { return "meet register constraints"; } 1257 1258 void Run(PipelineData* data, Zone* temp_zone) { 1259 ConstraintBuilder builder(data->register_allocation_data()); 1260 builder.MeetRegisterConstraints(); 1261 } 1262 }; 1263 1264 1265 struct ResolvePhisPhase { 1266 static const char* phase_name() { return "resolve phis"; } 1267 1268 void Run(PipelineData* data, Zone* temp_zone) { 1269 ConstraintBuilder builder(data->register_allocation_data()); 1270 builder.ResolvePhis(); 1271 } 1272 }; 1273 1274 1275 struct BuildLiveRangesPhase { 1276 static const char* phase_name() { return "build live ranges"; } 1277 1278 void Run(PipelineData* data, Zone* temp_zone) { 1279 LiveRangeBuilder builder(data->register_allocation_data(), temp_zone); 1280 builder.BuildLiveRanges(); 1281 } 1282 }; 1283 1284 1285 struct SplinterLiveRangesPhase { 1286 static const char* phase_name() { return "splinter live ranges"; } 1287 1288 void Run(PipelineData* data, Zone* temp_zone) { 1289 LiveRangeSeparator live_range_splinterer(data->register_allocation_data(), 1290 temp_zone); 1291 live_range_splinterer.Splinter(); 1292 } 1293 }; 1294 1295 1296 template <typename RegAllocator> 1297 struct AllocateGeneralRegistersPhase { 1298 static const char* phase_name() { return "allocate general registers"; } 1299 1300 void Run(PipelineData* data, Zone* temp_zone) { 1301 RegAllocator allocator(data->register_allocation_data(), GENERAL_REGISTERS, 1302 temp_zone); 1303 allocator.AllocateRegisters(); 1304 } 1305 }; 1306 1307 template <typename RegAllocator> 1308 struct AllocateFPRegistersPhase { 1309 static const char* phase_name() { 1310 return "allocate floating point registers"; 1311 } 1312 1313 void Run(PipelineData* data, Zone* temp_zone) { 1314 RegAllocator allocator(data->register_allocation_data(), FP_REGISTERS, 1315 temp_zone); 1316 allocator.AllocateRegisters(); 1317 } 1318 }; 1319 1320 1321 struct MergeSplintersPhase { 1322 static const char* phase_name() { return "merge splintered ranges"; } 1323 void Run(PipelineData* pipeline_data, Zone* temp_zone) { 1324 RegisterAllocationData* data = pipeline_data->register_allocation_data(); 1325 LiveRangeMerger live_range_merger(data, temp_zone); 1326 live_range_merger.Merge(); 1327 } 1328 }; 1329 1330 1331 struct LocateSpillSlotsPhase { 1332 static const char* phase_name() { return "locate spill slots"; } 1333 1334 void Run(PipelineData* data, Zone* temp_zone) { 1335 SpillSlotLocator locator(data->register_allocation_data()); 1336 locator.LocateSpillSlots(); 1337 } 1338 }; 1339 1340 1341 struct AssignSpillSlotsPhase { 1342 static const char* phase_name() { return "assign spill slots"; } 1343 1344 void Run(PipelineData* data, Zone* temp_zone) { 1345 OperandAssigner assigner(data->register_allocation_data()); 1346 assigner.AssignSpillSlots(); 1347 } 1348 }; 1349 1350 1351 struct CommitAssignmentPhase { 1352 static const char* phase_name() { return "commit assignment"; } 1353 1354 void Run(PipelineData* data, Zone* temp_zone) { 1355 OperandAssigner assigner(data->register_allocation_data()); 1356 assigner.CommitAssignment(); 1357 } 1358 }; 1359 1360 1361 struct PopulateReferenceMapsPhase { 1362 static const char* phase_name() { return "populate pointer maps"; } 1363 1364 void Run(PipelineData* data, Zone* temp_zone) { 1365 ReferenceMapPopulator populator(data->register_allocation_data()); 1366 populator.PopulateReferenceMaps(); 1367 } 1368 }; 1369 1370 1371 struct ConnectRangesPhase { 1372 static const char* phase_name() { return "connect ranges"; } 1373 1374 void Run(PipelineData* data, Zone* temp_zone) { 1375 LiveRangeConnector connector(data->register_allocation_data()); 1376 connector.ConnectRanges(temp_zone); 1377 } 1378 }; 1379 1380 1381 struct ResolveControlFlowPhase { 1382 static const char* phase_name() { return "resolve control flow"; } 1383 1384 void Run(PipelineData* data, Zone* temp_zone) { 1385 LiveRangeConnector connector(data->register_allocation_data()); 1386 connector.ResolveControlFlow(temp_zone); 1387 } 1388 }; 1389 1390 1391 struct OptimizeMovesPhase { 1392 static const char* phase_name() { return "optimize moves"; } 1393 1394 void Run(PipelineData* data, Zone* temp_zone) { 1395 MoveOptimizer move_optimizer(temp_zone, data->sequence()); 1396 move_optimizer.Run(); 1397 } 1398 }; 1399 1400 1401 struct FrameElisionPhase { 1402 static const char* phase_name() { return "frame elision"; } 1403 1404 void Run(PipelineData* data, Zone* temp_zone) { 1405 FrameElider(data->sequence()).Run(); 1406 } 1407 }; 1408 1409 1410 struct JumpThreadingPhase { 1411 static const char* phase_name() { return "jump threading"; } 1412 1413 void Run(PipelineData* data, Zone* temp_zone, bool frame_at_start) { 1414 ZoneVector<RpoNumber> result(temp_zone); 1415 if (JumpThreading::ComputeForwarding(temp_zone, result, data->sequence(), 1416 frame_at_start)) { 1417 JumpThreading::ApplyForwarding(result, data->sequence()); 1418 } 1419 } 1420 }; 1421 1422 1423 struct GenerateCodePhase { 1424 static const char* phase_name() { return "generate code"; } 1425 1426 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { 1427 CodeGenerator generator(data->frame(), linkage, data->sequence(), 1428 data->info()); 1429 data->set_code(generator.GenerateCode()); 1430 } 1431 }; 1432 1433 1434 struct PrintGraphPhase { 1435 static const char* phase_name() { return nullptr; } 1436 1437 void Run(PipelineData* data, Zone* temp_zone, const char* phase) { 1438 CompilationInfo* info = data->info(); 1439 Graph* graph = data->graph(); 1440 1441 { // Print JSON. 1442 AllowHandleDereference allow_deref; 1443 TurboJsonFile json_of(info, std::ios_base::app); 1444 json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":" 1445 << AsJSON(*graph, data->source_positions()) << "},\n"; 1446 } 1447 1448 if (FLAG_trace_turbo_graph) { // Simple textual RPO. 1449 AllowHandleDereference allow_deref; 1450 CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); 1451 OFStream os(tracing_scope.file()); 1452 os << "-- Graph after " << phase << " -- " << std::endl; 1453 os << AsRPO(*graph); 1454 } 1455 } 1456 }; 1457 1458 1459 struct VerifyGraphPhase { 1460 static const char* phase_name() { return nullptr; } 1461 1462 void Run(PipelineData* data, Zone* temp_zone, const bool untyped, 1463 bool values_only = false) { 1464 Verifier::Run(data->graph(), !untyped ? Verifier::TYPED : Verifier::UNTYPED, 1465 values_only ? Verifier::kValuesOnly : Verifier::kAll); 1466 } 1467 }; 1468 1469 void PipelineImpl::RunPrintAndVerify(const char* phase, bool untyped) { 1470 if (FLAG_trace_turbo) { 1471 Run<PrintGraphPhase>(phase); 1472 } 1473 if (FLAG_turbo_verify) { 1474 Run<VerifyGraphPhase>(untyped); 1475 } 1476 } 1477 1478 bool PipelineImpl::CreateGraph() { 1479 PipelineData* data = this->data_; 1480 1481 data->BeginPhaseKind("graph creation"); 1482 1483 if (FLAG_trace_turbo) { 1484 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); 1485 OFStream os(tracing_scope.file()); 1486 os << "---------------------------------------------------\n" 1487 << "Begin compiling method " << info()->GetDebugName().get() 1488 << " using Turbofan" << std::endl; 1489 TurboCfgFile tcf(isolate()); 1490 tcf << AsC1VCompilation(info()); 1491 } 1492 1493 data->source_positions()->AddDecorator(); 1494 1495 if (FLAG_loop_assignment_analysis) { 1496 Run<LoopAssignmentAnalysisPhase>(); 1497 } 1498 1499 Run<GraphBuilderPhase>(); 1500 if (data->compilation_failed()) { 1501 data->EndPhaseKind(); 1502 return false; 1503 } 1504 RunPrintAndVerify("Initial untyped", true); 1505 1506 // Perform OSR deconstruction. 1507 if (info()->is_osr()) { 1508 Run<OsrDeconstructionPhase>(); 1509 1510 Run<UntyperPhase>(); 1511 RunPrintAndVerify("OSR deconstruction", true); 1512 } 1513 1514 // Perform function context specialization and inlining (if enabled). 1515 Run<InliningPhase>(); 1516 RunPrintAndVerify("Inlined", true); 1517 1518 // Remove dead->live edges from the graph. 1519 Run<EarlyGraphTrimmingPhase>(); 1520 RunPrintAndVerify("Early trimmed", true); 1521 1522 if (FLAG_print_turbo_replay) { 1523 // Print a replay of the initial graph. 1524 GraphReplayPrinter::PrintReplay(data->graph()); 1525 } 1526 1527 // Run the type-sensitive lowerings and optimizations on the graph. 1528 { 1529 // Determine the Typer operation flags. 1530 Typer::Flags flags = Typer::kNoFlags; 1531 if (is_sloppy(info()->shared_info()->language_mode()) && 1532 info()->shared_info()->IsUserJavaScript()) { 1533 // Sloppy mode functions always have an Object for this. 1534 flags |= Typer::kThisIsReceiver; 1535 } 1536 if (IsClassConstructor(info()->shared_info()->kind())) { 1537 // Class constructors cannot be [[Call]]ed. 1538 flags |= Typer::kNewTargetIsReceiver; 1539 } 1540 1541 // Type the graph and keep the Typer running on newly created nodes within 1542 // this scope; the Typer is automatically unlinked from the Graph once we 1543 // leave this scope below. 1544 Typer typer(isolate(), flags, data->graph()); 1545 Run<TyperPhase>(&typer); 1546 RunPrintAndVerify("Typed"); 1547 1548 data->BeginPhaseKind("lowering"); 1549 1550 // Lower JSOperators where we can determine types. 1551 Run<TypedLoweringPhase>(); 1552 RunPrintAndVerify("Lowered typed"); 1553 } 1554 1555 // Do some hacky things to prepare for the optimization phase. 1556 // (caching handles, etc.). 1557 Run<ConcurrentOptimizationPrepPhase>(); 1558 1559 data->EndPhaseKind(); 1560 1561 return true; 1562 } 1563 1564 bool PipelineImpl::OptimizeGraph(Linkage* linkage) { 1565 PipelineData* data = this->data_; 1566 1567 if (data->info()->is_loop_peeling_enabled()) { 1568 Run<LoopPeelingPhase>(); 1569 RunPrintAndVerify("Loops peeled", true); 1570 } else { 1571 Run<LoopExitEliminationPhase>(); 1572 RunPrintAndVerify("Loop exits eliminated", true); 1573 } 1574 1575 if (!data->is_asm()) { 1576 if (FLAG_turbo_load_elimination) { 1577 Run<LoadEliminationPhase>(); 1578 RunPrintAndVerify("Load eliminated"); 1579 } 1580 1581 if (FLAG_turbo_escape) { 1582 Run<EscapeAnalysisPhase>(); 1583 if (data->compilation_failed()) { 1584 info()->AbortOptimization(kCyclicObjectStateDetectedInEscapeAnalysis); 1585 data->EndPhaseKind(); 1586 return false; 1587 } 1588 RunPrintAndVerify("Escape Analysed"); 1589 } 1590 } 1591 1592 // Perform simplified lowering. This has to run w/o the Typer decorator, 1593 // because we cannot compute meaningful types anyways, and the computed types 1594 // might even conflict with the representation/truncation logic. 1595 Run<SimplifiedLoweringPhase>(); 1596 RunPrintAndVerify("Simplified lowering", true); 1597 1598 #ifdef DEBUG 1599 // From now on it is invalid to look at types on the nodes, because: 1600 // 1601 // (a) The remaining passes (might) run concurrent to the main thread and 1602 // therefore must not access the Heap or the Isolate in an uncontrolled 1603 // way (as done by the type system), and 1604 // (b) the types on the nodes might not make sense after representation 1605 // selection due to the way we handle truncations; if we'd want to look 1606 // at types afterwards we'd essentially need to re-type (large portions 1607 // of) the graph. 1608 // 1609 // In order to catch bugs related to type access after this point we remove 1610 // the types from the nodes at this point (currently only in Debug builds). 1611 Run<UntyperPhase>(); 1612 RunPrintAndVerify("Untyped", true); 1613 #endif 1614 1615 // Run generic lowering pass. 1616 Run<GenericLoweringPhase>(); 1617 RunPrintAndVerify("Generic lowering", true); 1618 1619 data->BeginPhaseKind("block building"); 1620 1621 // Run early optimization pass. 1622 Run<EarlyOptimizationPhase>(); 1623 RunPrintAndVerify("Early optimized", true); 1624 1625 Run<EffectControlLinearizationPhase>(); 1626 RunPrintAndVerify("Effect and control linearized", true); 1627 1628 Run<DeadCodeEliminationPhase>(); 1629 RunPrintAndVerify("Dead code elimination", true); 1630 1631 if (FLAG_turbo_store_elimination) { 1632 Run<StoreStoreEliminationPhase>(); 1633 RunPrintAndVerify("Store-store elimination", true); 1634 } 1635 1636 // Optimize control flow. 1637 if (FLAG_turbo_cf_optimization) { 1638 Run<ControlFlowOptimizationPhase>(); 1639 RunPrintAndVerify("Control flow optimized", true); 1640 } 1641 1642 // Optimize memory access and allocation operations. 1643 Run<MemoryOptimizationPhase>(); 1644 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. 1645 RunPrintAndVerify("Memory optimized", true); 1646 1647 // Lower changes that have been inserted before. 1648 Run<LateOptimizationPhase>(); 1649 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. 1650 RunPrintAndVerify("Late optimized", true); 1651 1652 data->source_positions()->RemoveDecorator(); 1653 1654 return ScheduleAndSelectInstructions(linkage, true); 1655 } 1656 1657 Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate, 1658 CallDescriptor* call_descriptor, 1659 Graph* graph, Schedule* schedule, 1660 Code::Flags flags, 1661 const char* debug_name) { 1662 CompilationInfo info(CStrVector(debug_name), isolate, graph->zone(), flags); 1663 if (isolate->serializer_enabled()) info.PrepareForSerializing(); 1664 1665 // Construct a pipeline for scheduling and code generation. 1666 ZoneStats zone_stats(isolate->allocator()); 1667 SourcePositionTable source_positions(graph); 1668 PipelineData data(&zone_stats, &info, graph, schedule, &source_positions); 1669 data.set_verify_graph(FLAG_verify_csa); 1670 std::unique_ptr<PipelineStatistics> pipeline_statistics; 1671 if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) { 1672 pipeline_statistics.reset(new PipelineStatistics(&info, &zone_stats)); 1673 pipeline_statistics->BeginPhaseKind("stub codegen"); 1674 } 1675 1676 PipelineImpl pipeline(&data); 1677 DCHECK_NOT_NULL(data.schedule()); 1678 1679 if (FLAG_trace_turbo) { 1680 { 1681 CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); 1682 OFStream os(tracing_scope.file()); 1683 os << "---------------------------------------------------\n" 1684 << "Begin compiling " << debug_name << " using Turbofan" << std::endl; 1685 } 1686 { 1687 TurboJsonFile json_of(&info, std::ios_base::trunc); 1688 json_of << "{\"function\":\"" << info.GetDebugName().get() 1689 << "\", \"source\":\"\",\n\"phases\":["; 1690 } 1691 pipeline.Run<PrintGraphPhase>("Machine"); 1692 } 1693 1694 pipeline.Run<VerifyGraphPhase>(false, true); 1695 return pipeline.ScheduleAndGenerateCode(call_descriptor); 1696 } 1697 1698 // static 1699 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info) { 1700 ZoneStats zone_stats(info->isolate()->allocator()); 1701 std::unique_ptr<PipelineStatistics> pipeline_statistics( 1702 CreatePipelineStatistics(info, &zone_stats)); 1703 PipelineData data(&zone_stats, info, pipeline_statistics.get()); 1704 PipelineImpl pipeline(&data); 1705 1706 Linkage linkage(Linkage::ComputeIncoming(data.instruction_zone(), info)); 1707 1708 if (!pipeline.CreateGraph()) return Handle<Code>::null(); 1709 if (!pipeline.OptimizeGraph(&linkage)) return Handle<Code>::null(); 1710 return pipeline.GenerateCode(&linkage); 1711 } 1712 1713 // static 1714 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, 1715 Graph* graph, 1716 Schedule* schedule) { 1717 CallDescriptor* call_descriptor = 1718 Linkage::ComputeIncoming(info->zone(), info); 1719 return GenerateCodeForTesting(info, call_descriptor, graph, schedule); 1720 } 1721 1722 // static 1723 Handle<Code> Pipeline::GenerateCodeForTesting( 1724 CompilationInfo* info, CallDescriptor* call_descriptor, Graph* graph, 1725 Schedule* schedule, SourcePositionTable* source_positions) { 1726 // Construct a pipeline for scheduling and code generation. 1727 ZoneStats zone_stats(info->isolate()->allocator()); 1728 // TODO(wasm): Refactor code generation to check for non-existing source 1729 // table, then remove this conditional allocation. 1730 if (!source_positions) 1731 source_positions = new (info->zone()) SourcePositionTable(graph); 1732 PipelineData data(&zone_stats, info, graph, schedule, source_positions); 1733 std::unique_ptr<PipelineStatistics> pipeline_statistics; 1734 if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) { 1735 pipeline_statistics.reset(new PipelineStatistics(info, &zone_stats)); 1736 pipeline_statistics->BeginPhaseKind("test codegen"); 1737 } 1738 1739 PipelineImpl pipeline(&data); 1740 1741 if (FLAG_trace_turbo) { 1742 TurboJsonFile json_of(info, std::ios_base::trunc); 1743 json_of << "{\"function\":\"" << info->GetDebugName().get() 1744 << "\", \"source\":\"\",\n\"phases\":["; 1745 } 1746 // TODO(rossberg): Should this really be untyped? 1747 pipeline.RunPrintAndVerify("Machine", true); 1748 1749 return pipeline.ScheduleAndGenerateCode(call_descriptor); 1750 } 1751 1752 // static 1753 CompilationJob* Pipeline::NewCompilationJob(Handle<JSFunction> function, 1754 bool has_script) { 1755 Handle<SharedFunctionInfo> shared = handle(function->shared()); 1756 ParseInfo* parse_info; 1757 if (!has_script) { 1758 parse_info = ParseInfo::AllocateWithoutScript(shared); 1759 } else { 1760 parse_info = new ParseInfo(shared); 1761 } 1762 return new PipelineCompilationJob(parse_info, function); 1763 } 1764 1765 // static 1766 CompilationJob* Pipeline::NewWasmCompilationJob( 1767 CompilationInfo* info, JSGraph* jsgraph, CallDescriptor* descriptor, 1768 SourcePositionTable* source_positions, 1769 ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions, 1770 bool allow_signalling_nan) { 1771 return new PipelineWasmCompilationJob( 1772 info, jsgraph, descriptor, source_positions, protected_instructions, 1773 allow_signalling_nan); 1774 } 1775 1776 bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, 1777 InstructionSequence* sequence, 1778 bool run_verifier) { 1779 CompilationInfo info(ArrayVector("testing"), sequence->isolate(), 1780 sequence->zone(), Code::ComputeFlags(Code::STUB)); 1781 ZoneStats zone_stats(sequence->isolate()->allocator()); 1782 PipelineData data(&zone_stats, &info, sequence); 1783 PipelineImpl pipeline(&data); 1784 pipeline.data_->InitializeFrameData(nullptr); 1785 pipeline.AllocateRegisters(config, nullptr, run_verifier); 1786 return !data.compilation_failed(); 1787 } 1788 1789 bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage, 1790 bool trim_graph) { 1791 CallDescriptor* call_descriptor = linkage->GetIncomingDescriptor(); 1792 PipelineData* data = this->data_; 1793 1794 DCHECK_NOT_NULL(data->graph()); 1795 1796 if (trim_graph) { 1797 Run<LateGraphTrimmingPhase>(); 1798 RunPrintAndVerify("Late trimmed", true); 1799 } 1800 if (data->schedule() == nullptr) Run<ComputeSchedulePhase>(); 1801 TraceSchedule(data->info(), data->schedule()); 1802 1803 if (FLAG_turbo_profiling) { 1804 data->set_profiler_data(BasicBlockInstrumentor::Instrument( 1805 info(), data->graph(), data->schedule())); 1806 } 1807 1808 bool verify_stub_graph = data->verify_graph(); 1809 if (verify_stub_graph || 1810 (FLAG_turbo_verify_machine_graph != nullptr && 1811 (!strcmp(FLAG_turbo_verify_machine_graph, "*") || 1812 !strcmp(FLAG_turbo_verify_machine_graph, data->debug_name())))) { 1813 if (FLAG_trace_verify_csa) { 1814 AllowHandleDereference allow_deref; 1815 CompilationInfo* info = data->info(); 1816 CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); 1817 OFStream os(tracing_scope.file()); 1818 os << "--------------------------------------------------\n" 1819 << "--- Verifying " << data->debug_name() << " generated by TurboFan\n" 1820 << "--------------------------------------------------\n" 1821 << *data->schedule() 1822 << "--------------------------------------------------\n" 1823 << "--- End of " << data->debug_name() << " generated by TurboFan\n" 1824 << "--------------------------------------------------\n"; 1825 } 1826 Zone temp_zone(data->isolate()->allocator(), ZONE_NAME); 1827 MachineGraphVerifier::Run(data->graph(), data->schedule(), linkage, 1828 data->info()->IsStub(), data->debug_name(), 1829 &temp_zone); 1830 } 1831 1832 data->InitializeInstructionSequence(call_descriptor); 1833 1834 data->InitializeFrameData(call_descriptor); 1835 // Select and schedule instructions covering the scheduled graph. 1836 Run<InstructionSelectionPhase>(linkage); 1837 if (data->compilation_failed()) { 1838 info()->AbortOptimization(kCodeGenerationFailed); 1839 data->EndPhaseKind(); 1840 return false; 1841 } 1842 1843 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { 1844 AllowHandleDereference allow_deref; 1845 TurboCfgFile tcf(isolate()); 1846 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), 1847 data->sequence()); 1848 } 1849 1850 if (FLAG_trace_turbo) { 1851 std::ostringstream source_position_output; 1852 // Output source position information before the graph is deleted. 1853 data_->source_positions()->Print(source_position_output); 1854 data_->set_source_position_output(source_position_output.str()); 1855 } 1856 1857 data->DeleteGraphZone(); 1858 1859 data->BeginPhaseKind("register allocation"); 1860 1861 bool run_verifier = FLAG_turbo_verify_allocation; 1862 1863 // Allocate registers. 1864 AllocateRegisters(RegisterConfiguration::Turbofan(), call_descriptor, 1865 run_verifier); 1866 Run<FrameElisionPhase>(); 1867 if (data->compilation_failed()) { 1868 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); 1869 data->EndPhaseKind(); 1870 return false; 1871 } 1872 1873 // TODO(mtrofin): move this off to the register allocator. 1874 bool generate_frame_at_start = 1875 data_->sequence()->instruction_blocks().front()->must_construct_frame(); 1876 // Optimimize jumps. 1877 if (FLAG_turbo_jt) { 1878 Run<JumpThreadingPhase>(generate_frame_at_start); 1879 } 1880 1881 data->EndPhaseKind(); 1882 1883 return true; 1884 } 1885 1886 Handle<Code> PipelineImpl::GenerateCode(Linkage* linkage) { 1887 PipelineData* data = this->data_; 1888 1889 data->BeginPhaseKind("code generation"); 1890 1891 // Generate final machine code. 1892 Run<GenerateCodePhase>(linkage); 1893 1894 Handle<Code> code = data->code(); 1895 if (data->profiler_data()) { 1896 #if ENABLE_DISASSEMBLER 1897 std::ostringstream os; 1898 code->Disassemble(nullptr, os); 1899 data->profiler_data()->SetCode(&os); 1900 #endif 1901 } 1902 1903 info()->SetCode(code); 1904 v8::internal::CodeGenerator::PrintCode(code, info()); 1905 1906 if (FLAG_trace_turbo) { 1907 TurboJsonFile json_of(info(), std::ios_base::app); 1908 json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\""; 1909 #if ENABLE_DISASSEMBLER 1910 std::stringstream disassembly_stream; 1911 code->Disassemble(nullptr, disassembly_stream); 1912 std::string disassembly_string(disassembly_stream.str()); 1913 for (const auto& c : disassembly_string) { 1914 json_of << AsEscapedUC16ForJSON(c); 1915 } 1916 #endif // ENABLE_DISASSEMBLER 1917 json_of << "\"}\n],\n"; 1918 json_of << "\"nodePositions\":"; 1919 json_of << data->source_position_output(); 1920 json_of << "}"; 1921 1922 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); 1923 OFStream os(tracing_scope.file()); 1924 os << "---------------------------------------------------\n" 1925 << "Finished compiling method " << info()->GetDebugName().get() 1926 << " using Turbofan" << std::endl; 1927 } 1928 1929 return code; 1930 } 1931 1932 Handle<Code> PipelineImpl::ScheduleAndGenerateCode( 1933 CallDescriptor* call_descriptor) { 1934 Linkage linkage(call_descriptor); 1935 1936 // Schedule the graph, perform instruction selection and register allocation. 1937 if (!ScheduleAndSelectInstructions(&linkage, false)) return Handle<Code>(); 1938 1939 // Generate the final machine code. 1940 return GenerateCode(&linkage); 1941 } 1942 1943 void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config, 1944 CallDescriptor* descriptor, 1945 bool run_verifier) { 1946 PipelineData* data = this->data_; 1947 // Don't track usage for this zone in compiler stats. 1948 std::unique_ptr<Zone> verifier_zone; 1949 RegisterAllocatorVerifier* verifier = nullptr; 1950 if (run_verifier) { 1951 verifier_zone.reset(new Zone(isolate()->allocator(), ZONE_NAME)); 1952 verifier = new (verifier_zone.get()) RegisterAllocatorVerifier( 1953 verifier_zone.get(), config, data->sequence()); 1954 } 1955 1956 #ifdef DEBUG 1957 data_->sequence()->ValidateEdgeSplitForm(); 1958 data_->sequence()->ValidateDeferredBlockEntryPaths(); 1959 data_->sequence()->ValidateDeferredBlockExitPaths(); 1960 #endif 1961 1962 data->InitializeRegisterAllocationData(config, descriptor); 1963 if (info()->is_osr()) { 1964 AllowHandleDereference allow_deref; 1965 OsrHelper osr_helper(info()); 1966 osr_helper.SetupFrame(data->frame()); 1967 } 1968 1969 Run<MeetRegisterConstraintsPhase>(); 1970 Run<ResolvePhisPhase>(); 1971 Run<BuildLiveRangesPhase>(); 1972 if (FLAG_trace_turbo_graph) { 1973 AllowHandleDereference allow_deref; 1974 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); 1975 OFStream os(tracing_scope.file()); 1976 os << "----- Instruction sequence before register allocation -----\n" 1977 << PrintableInstructionSequence({config, data->sequence()}); 1978 } 1979 if (verifier != nullptr) { 1980 CHECK(!data->register_allocation_data()->ExistsUseWithoutDefinition()); 1981 CHECK(data->register_allocation_data() 1982 ->RangesDefinedInDeferredStayInDeferred()); 1983 } 1984 1985 if (FLAG_turbo_preprocess_ranges) { 1986 Run<SplinterLiveRangesPhase>(); 1987 } 1988 1989 Run<AllocateGeneralRegistersPhase<LinearScanAllocator>>(); 1990 Run<AllocateFPRegistersPhase<LinearScanAllocator>>(); 1991 1992 if (FLAG_turbo_preprocess_ranges) { 1993 Run<MergeSplintersPhase>(); 1994 } 1995 1996 Run<AssignSpillSlotsPhase>(); 1997 1998 Run<CommitAssignmentPhase>(); 1999 Run<PopulateReferenceMapsPhase>(); 2000 Run<ConnectRangesPhase>(); 2001 Run<ResolveControlFlowPhase>(); 2002 if (FLAG_turbo_move_optimization) { 2003 Run<OptimizeMovesPhase>(); 2004 } 2005 2006 Run<LocateSpillSlotsPhase>(); 2007 2008 if (FLAG_trace_turbo_graph) { 2009 AllowHandleDereference allow_deref; 2010 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); 2011 OFStream os(tracing_scope.file()); 2012 os << "----- Instruction sequence after register allocation -----\n" 2013 << PrintableInstructionSequence({config, data->sequence()}); 2014 } 2015 2016 if (verifier != nullptr) { 2017 verifier->VerifyAssignment(); 2018 verifier->VerifyGapMoves(); 2019 } 2020 2021 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { 2022 TurboCfgFile tcf(data->isolate()); 2023 tcf << AsC1VRegisterAllocationData("CodeGen", 2024 data->register_allocation_data()); 2025 } 2026 2027 data->DeleteRegisterAllocationZone(); 2028 } 2029 2030 CompilationInfo* PipelineImpl::info() const { return data_->info(); } 2031 2032 Isolate* PipelineImpl::isolate() const { return info()->isolate(); } 2033 2034 } // namespace compiler 2035 } // namespace internal 2036 } // namespace v8 2037