blob: 21c34fc77e80c77e6be587c5a5fe7695687a72ae [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007#include <fstream> // NOLINT(readability/streams)
8#include <sstream>
9
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/base/adapters.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/base/platform/elapsed-timer.h"
12#include "src/compiler/ast-graph-builder.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013#include "src/compiler/ast-loop-assignment-analyzer.h"
14#include "src/compiler/basic-block-instrumentor.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015#include "src/compiler/branch-elimination.h"
16#include "src/compiler/bytecode-graph-builder.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/compiler/change-lowering.h"
18#include "src/compiler/code-generator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019#include "src/compiler/common-operator-reducer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020#include "src/compiler/control-flow-optimizer.h"
21#include "src/compiler/dead-code-elimination.h"
22#include "src/compiler/escape-analysis.h"
23#include "src/compiler/escape-analysis-reducer.h"
24#include "src/compiler/frame-elider.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025#include "src/compiler/graph-replay.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026#include "src/compiler/graph-trimmer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027#include "src/compiler/graph-visualizer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028#include "src/compiler/greedy-allocator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029#include "src/compiler/instruction.h"
30#include "src/compiler/instruction-selector.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040031#include "src/compiler/js-builtin-reducer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032#include "src/compiler/js-call-reducer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033#include "src/compiler/js-context-specialization.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010034#include "src/compiler/js-create-lowering.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035#include "src/compiler/js-frame-specialization.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036#include "src/compiler/js-generic-lowering.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037#include "src/compiler/js-global-object-specialization.h"
38#include "src/compiler/js-inlining-heuristic.h"
39#include "src/compiler/js-intrinsic-lowering.h"
40#include "src/compiler/js-native-context-specialization.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041#include "src/compiler/js-typed-lowering.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040042#include "src/compiler/jump-threading.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043#include "src/compiler/live-range-separator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040044#include "src/compiler/load-elimination.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045#include "src/compiler/loop-analysis.h"
46#include "src/compiler/loop-peeling.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047#include "src/compiler/machine-operator-reducer.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040048#include "src/compiler/move-optimizer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049#include "src/compiler/osr.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050#include "src/compiler/pipeline-statistics.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051#include "src/compiler/register-allocator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040052#include "src/compiler/register-allocator-verifier.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053#include "src/compiler/schedule.h"
54#include "src/compiler/scheduler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055#include "src/compiler/select-lowering.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056#include "src/compiler/simplified-lowering.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000057#include "src/compiler/simplified-operator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058#include "src/compiler/simplified-operator-reducer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059#include "src/compiler/tail-call-optimization.h"
60#include "src/compiler/type-hint-analyzer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061#include "src/compiler/typer.h"
62#include "src/compiler/value-numbering-reducer.h"
63#include "src/compiler/verifier.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040064#include "src/compiler/zone-pool.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065#include "src/ostreams.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066#include "src/register-configuration.h"
67#include "src/type-info.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068#include "src/utils.h"
69
70namespace v8 {
71namespace internal {
72namespace compiler {
73
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074class PipelineData {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 // For main entry point.
77 PipelineData(ZonePool* zone_pool, CompilationInfo* info,
78 PipelineStatistics* pipeline_statistics)
79 : isolate_(info->isolate()),
80 info_(info),
81 outer_zone_(info_->zone()),
82 zone_pool_(zone_pool),
83 pipeline_statistics_(pipeline_statistics),
84 compilation_failed_(false),
85 code_(Handle<Code>::null()),
86 graph_zone_scope_(zone_pool_),
87 graph_zone_(graph_zone_scope_.zone()),
88 graph_(nullptr),
89 loop_assignment_(nullptr),
90 simplified_(nullptr),
91 machine_(nullptr),
92 common_(nullptr),
93 javascript_(nullptr),
94 jsgraph_(nullptr),
95 schedule_(nullptr),
96 instruction_zone_scope_(zone_pool_),
97 instruction_zone_(instruction_zone_scope_.zone()),
98 sequence_(nullptr),
99 frame_(nullptr),
100 register_allocation_zone_scope_(zone_pool_),
101 register_allocation_zone_(register_allocation_zone_scope_.zone()),
102 register_allocation_data_(nullptr) {
103 PhaseScope scope(pipeline_statistics, "init pipeline data");
104 graph_ = new (graph_zone_) Graph(graph_zone_);
105 source_positions_.Reset(new SourcePositionTable(graph_));
106 simplified_ = new (graph_zone_) SimplifiedOperatorBuilder(graph_zone_);
107 machine_ = new (graph_zone_) MachineOperatorBuilder(
108 graph_zone_, MachineType::PointerRepresentation(),
109 InstructionSelector::SupportedMachineOperatorFlags());
110 common_ = new (graph_zone_) CommonOperatorBuilder(graph_zone_);
111 javascript_ = new (graph_zone_) JSOperatorBuilder(graph_zone_);
112 jsgraph_ = new (graph_zone_)
113 JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_);
114 }
115
116 // For machine graph testing entry point.
117 PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph,
118 Schedule* schedule)
119 : isolate_(info->isolate()),
120 info_(info),
121 outer_zone_(nullptr),
122 zone_pool_(zone_pool),
123 pipeline_statistics_(nullptr),
124 compilation_failed_(false),
125 code_(Handle<Code>::null()),
126 graph_zone_scope_(zone_pool_),
127 graph_zone_(nullptr),
128 graph_(graph),
129 source_positions_(new SourcePositionTable(graph_)),
130 loop_assignment_(nullptr),
131 simplified_(nullptr),
132 machine_(nullptr),
133 common_(nullptr),
134 javascript_(nullptr),
135 jsgraph_(nullptr),
136 schedule_(schedule),
137 instruction_zone_scope_(zone_pool_),
138 instruction_zone_(instruction_zone_scope_.zone()),
139 sequence_(nullptr),
140 frame_(nullptr),
141 register_allocation_zone_scope_(zone_pool_),
142 register_allocation_zone_(register_allocation_zone_scope_.zone()),
143 register_allocation_data_(nullptr) {}
144
145 // For register allocation testing entry point.
146 PipelineData(ZonePool* zone_pool, CompilationInfo* info,
147 InstructionSequence* sequence)
148 : isolate_(info->isolate()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149 info_(info),
150 outer_zone_(nullptr),
151 zone_pool_(zone_pool),
152 pipeline_statistics_(nullptr),
153 compilation_failed_(false),
154 code_(Handle<Code>::null()),
155 graph_zone_scope_(zone_pool_),
156 graph_zone_(nullptr),
157 graph_(nullptr),
158 loop_assignment_(nullptr),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159 simplified_(nullptr),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400160 machine_(nullptr),
161 common_(nullptr),
162 javascript_(nullptr),
163 jsgraph_(nullptr),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400164 schedule_(nullptr),
165 instruction_zone_scope_(zone_pool_),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166 instruction_zone_(sequence->zone()),
167 sequence_(sequence),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168 frame_(nullptr),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 register_allocation_zone_scope_(zone_pool_),
170 register_allocation_zone_(register_allocation_zone_scope_.zone()),
171 register_allocation_data_(nullptr) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000172
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173 ~PipelineData() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 DeleteRegisterAllocationZone();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400175 DeleteInstructionZone();
176 DeleteGraphZone();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177 }
178
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400179 Isolate* isolate() const { return isolate_; }
180 CompilationInfo* info() const { return info_; }
181 ZonePool* zone_pool() const { return zone_pool_; }
182 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; }
183 bool compilation_failed() const { return compilation_failed_; }
184 void set_compilation_failed() { compilation_failed_ = true; }
185 Handle<Code> code() { return code_; }
186 void set_code(Handle<Code> code) {
187 DCHECK(code_.is_null());
188 code_ = code;
189 }
190
191 // RawMachineAssembler generally produces graphs which cannot be verified.
192 bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; }
193
194 Zone* graph_zone() const { return graph_zone_; }
195 Graph* graph() const { return graph_; }
196 SourcePositionTable* source_positions() const {
197 return source_positions_.get();
198 }
199 MachineOperatorBuilder* machine() const { return machine_; }
200 CommonOperatorBuilder* common() const { return common_; }
201 JSOperatorBuilder* javascript() const { return javascript_; }
202 JSGraph* jsgraph() const { return jsgraph_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 MaybeHandle<Context> native_context() const {
204 if (info()->is_native_context_specializing()) {
205 return handle(info()->native_context(), isolate());
206 }
207 return MaybeHandle<Context>();
208 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400209
210 LoopAssignmentAnalysis* loop_assignment() const { return loop_assignment_; }
211 void set_loop_assignment(LoopAssignmentAnalysis* loop_assignment) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 DCHECK(!loop_assignment_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 loop_assignment_ = loop_assignment;
214 }
215
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 TypeHintAnalysis* type_hint_analysis() const { return type_hint_analysis_; }
217 void set_type_hint_analysis(TypeHintAnalysis* type_hint_analysis) {
218 DCHECK_NULL(type_hint_analysis_);
219 type_hint_analysis_ = type_hint_analysis;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220 }
221
222 Schedule* schedule() const { return schedule_; }
223 void set_schedule(Schedule* schedule) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 DCHECK(!schedule_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225 schedule_ = schedule;
226 }
227
228 Zone* instruction_zone() const { return instruction_zone_; }
229 InstructionSequence* sequence() const { return sequence_; }
230 Frame* frame() const { return frame_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231
232 Zone* register_allocation_zone() const { return register_allocation_zone_; }
233 RegisterAllocationData* register_allocation_data() const {
234 return register_allocation_data_;
235 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400236
237 void DeleteGraphZone() {
238 // Destroy objects with destructors first.
239 source_positions_.Reset(nullptr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400240 if (graph_zone_ == nullptr) return;
241 // Destroy zone and clear pointers.
242 graph_zone_scope_.Destroy();
243 graph_zone_ = nullptr;
244 graph_ = nullptr;
245 loop_assignment_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246 type_hint_analysis_ = nullptr;
247 simplified_ = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248 machine_ = nullptr;
249 common_ = nullptr;
250 javascript_ = nullptr;
251 jsgraph_ = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400252 schedule_ = nullptr;
253 }
254
255 void DeleteInstructionZone() {
256 if (instruction_zone_ == nullptr) return;
257 instruction_zone_scope_.Destroy();
258 instruction_zone_ = nullptr;
259 sequence_ = nullptr;
260 frame_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000261 }
262
263 void DeleteRegisterAllocationZone() {
264 if (register_allocation_zone_ == nullptr) return;
265 register_allocation_zone_scope_.Destroy();
266 register_allocation_zone_ = nullptr;
267 register_allocation_data_ = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400268 }
269
270 void InitializeInstructionSequence() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 DCHECK(sequence_ == nullptr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400272 InstructionBlocks* instruction_blocks =
273 InstructionSequence::InstructionBlocksFor(instruction_zone(),
274 schedule());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 sequence_ = new (instruction_zone()) InstructionSequence(
276 info()->isolate(), instruction_zone(), instruction_blocks);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400277 }
278
Ben Murdoch097c5b22016-05-18 11:27:45 +0100279 void InitializeFrameData(CallDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 DCHECK(frame_ == nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 int fixed_frame_size = 0;
282 if (descriptor != nullptr) {
283 fixed_frame_size = (descriptor->IsCFunctionCall())
284 ? StandardFrameConstants::kFixedSlotCountAboveFp +
285 StandardFrameConstants::kCPSlotCount
286 : StandardFrameConstants::kFixedSlotCount;
287 }
288 frame_ = new (instruction_zone()) Frame(fixed_frame_size, descriptor);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100289 }
290
291 void InitializeRegisterAllocationData(const RegisterConfiguration* config,
292 CallDescriptor* descriptor,
293 const char* debug_name) {
294 DCHECK(register_allocation_data_ == nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 register_allocation_data_ = new (register_allocation_zone())
296 RegisterAllocationData(config, register_allocation_zone(), frame(),
297 sequence(), debug_name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 }
299
300 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400301 Isolate* isolate_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 CompilationInfo* info_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400303 Zone* outer_zone_;
304 ZonePool* const zone_pool_;
305 PipelineStatistics* pipeline_statistics_;
306 bool compilation_failed_;
307 Handle<Code> code_;
308
309 // All objects in the following group of fields are allocated in graph_zone_.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 // They are all set to nullptr when the graph_zone_ is destroyed.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400311 ZonePool::Scope graph_zone_scope_;
312 Zone* graph_zone_;
313 Graph* graph_;
314 // TODO(dcarney): make this into a ZoneObject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315 base::SmartPointer<SourcePositionTable> source_positions_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400316 LoopAssignmentAnalysis* loop_assignment_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 TypeHintAnalysis* type_hint_analysis_ = nullptr;
318 SimplifiedOperatorBuilder* simplified_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400319 MachineOperatorBuilder* machine_;
320 CommonOperatorBuilder* common_;
321 JSOperatorBuilder* javascript_;
322 JSGraph* jsgraph_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400323 Schedule* schedule_;
324
325 // All objects in the following group of fields are allocated in
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000326 // instruction_zone_. They are all set to nullptr when the instruction_zone_
327 // is
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400328 // destroyed.
329 ZonePool::Scope instruction_zone_scope_;
330 Zone* instruction_zone_;
331 InstructionSequence* sequence_;
332 Frame* frame_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333
334 // All objects in the following group of fields are allocated in
335 // register_allocation_zone_. They are all set to nullptr when the zone is
336 // destroyed.
337 ZonePool::Scope register_allocation_zone_scope_;
338 Zone* register_allocation_zone_;
339 RegisterAllocationData* register_allocation_data_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340
341 DISALLOW_COPY_AND_ASSIGN(PipelineData);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342};
343
344
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345namespace {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400347struct TurboCfgFile : public std::ofstream {
348 explicit TurboCfgFile(Isolate* isolate)
349 : std::ofstream(isolate->GetTurboCfgFileName().c_str(),
350 std::ios_base::app) {}
351};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400353
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354void TraceSchedule(CompilationInfo* info, Schedule* schedule) {
355 if (FLAG_trace_turbo) {
356 FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "a+");
357 if (json_file != nullptr) {
358 OFStream json_of(json_file);
359 json_of << "{\"name\":\"Schedule\",\"type\":\"schedule\",\"data\":\"";
360 std::stringstream schedule_stream;
361 schedule_stream << *schedule;
362 std::string schedule_string(schedule_stream.str());
363 for (const auto& c : schedule_string) {
364 json_of << AsEscapedUC16ForJSON(c);
365 }
366 json_of << "\"},\n";
367 fclose(json_file);
368 }
369 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400370 if (!FLAG_trace_turbo_graph && !FLAG_trace_turbo_scheduler) return;
371 OFStream os(stdout);
372 os << "-- Schedule --------------------------------------\n" << *schedule;
373}
374
375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000376class AstGraphBuilderWithPositions final : public AstGraphBuilder {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400378 AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
379 JSGraph* jsgraph,
380 LoopAssignmentAnalysis* loop_assignment,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 TypeHintAnalysis* type_hint_analysis,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400382 SourcePositionTable* source_positions)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 : AstGraphBuilder(local_zone, info, jsgraph, loop_assignment,
384 type_hint_analysis),
385 source_positions_(source_positions),
386 start_position_(info->shared_info()->start_position()) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 bool CreateGraph(bool stack_check) {
389 SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
390 return AstGraphBuilder::CreateGraph(stack_check);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000391 }
392
393#define DEF_VISIT(type) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394 void Visit##type(type* node) override { \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 SourcePositionTable::Scope pos(source_positions_, \
396 SourcePosition(node->position())); \
397 AstGraphBuilder::Visit##type(node); \
398 }
399 AST_NODE_LIST(DEF_VISIT)
400#undef DEF_VISIT
401
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 private:
403 SourcePositionTable* const source_positions_;
404 SourcePosition const start_position_;
405};
406
407
408class SourcePositionWrapper final : public Reducer {
409 public:
410 SourcePositionWrapper(Reducer* reducer, SourcePositionTable* table)
411 : reducer_(reducer), table_(table) {}
412 ~SourcePositionWrapper() final {}
413
414 Reduction Reduce(Node* node) final {
415 SourcePosition const pos = table_->GetSourcePosition(node);
416 SourcePositionTable::Scope position(table_, pos);
417 return reducer_->Reduce(node);
418 }
419
420 void Finalize() final { reducer_->Finalize(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400421
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423 Reducer* const reducer_;
424 SourcePositionTable* const table_;
425
426 DISALLOW_COPY_AND_ASSIGN(SourcePositionWrapper);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427};
428
429
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430class JSGraphReducer final : public GraphReducer {
431 public:
432 JSGraphReducer(JSGraph* jsgraph, Zone* zone)
433 : GraphReducer(zone, jsgraph->graph(), jsgraph->Dead()) {}
434 ~JSGraphReducer() final {}
435};
436
437
438void AddReducer(PipelineData* data, GraphReducer* graph_reducer,
439 Reducer* reducer) {
440 if (data->info()->is_source_positions_enabled()) {
441 void* const buffer = data->graph_zone()->New(sizeof(SourcePositionWrapper));
442 SourcePositionWrapper* const wrapper =
443 new (buffer) SourcePositionWrapper(reducer, data->source_positions());
444 graph_reducer->AddReducer(wrapper);
445 } else {
446 graph_reducer->AddReducer(reducer);
447 }
448}
449
450
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400451class PipelineRunScope {
452 public:
453 PipelineRunScope(PipelineData* data, const char* phase_name)
454 : phase_scope_(
455 phase_name == nullptr ? nullptr : data->pipeline_statistics(),
456 phase_name),
457 zone_scope_(data->zone_pool()) {}
458
459 Zone* zone() { return zone_scope_.zone(); }
460
461 private:
462 PhaseScope phase_scope_;
463 ZonePool::Scope zone_scope_;
464};
465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466} // namespace
467
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400468
469template <typename Phase>
470void Pipeline::Run() {
471 PipelineRunScope scope(this->data_, Phase::phase_name());
472 Phase phase;
473 phase.Run(this->data_, scope.zone());
474}
475
476
477template <typename Phase, typename Arg0>
478void Pipeline::Run(Arg0 arg_0) {
479 PipelineRunScope scope(this->data_, Phase::phase_name());
480 Phase phase;
481 phase.Run(this->data_, scope.zone(), arg_0);
482}
483
484
485struct LoopAssignmentAnalysisPhase {
486 static const char* phase_name() { return "loop assignment analysis"; }
487
488 void Run(PipelineData* data, Zone* temp_zone) {
489 AstLoopAssignmentAnalyzer analyzer(data->graph_zone(), data->info());
490 LoopAssignmentAnalysis* loop_assignment = analyzer.Analyze();
491 data->set_loop_assignment(loop_assignment);
492 }
493};
494
495
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496struct TypeHintAnalysisPhase {
497 static const char* phase_name() { return "type hint analysis"; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400498
499 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 TypeHintAnalyzer analyzer(data->graph_zone());
501 Handle<Code> code(data->info()->shared_info()->code(), data->isolate());
502 TypeHintAnalysis* type_hint_analysis = analyzer.Analyze(code);
503 data->set_type_hint_analysis(type_hint_analysis);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400504 }
505};
506
507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508struct GraphBuilderPhase {
509 static const char* phase_name() { return "graph builder"; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400510
511 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 bool stack_check = !data->info()->IsStub();
513 bool succeeded = false;
514
515 if (data->info()->shared_info()->HasBytecodeArray()) {
516 BytecodeGraphBuilder graph_builder(temp_zone, data->info(),
517 data->jsgraph());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100518 succeeded = graph_builder.CreateGraph();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 } else {
520 AstGraphBuilderWithPositions graph_builder(
521 temp_zone, data->info(), data->jsgraph(), data->loop_assignment(),
522 data->type_hint_analysis(), data->source_positions());
523 succeeded = graph_builder.CreateGraph(stack_check);
524 }
525
526 if (!succeeded) {
527 data->set_compilation_failed();
528 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400529 }
530};
531
532
533struct InliningPhase {
534 static const char* phase_name() { return "inlining"; }
535
536 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
538 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
539 data->common());
540 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
541 data->common(), data->machine());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100542 JSCallReducer call_reducer(&graph_reducer, data->jsgraph(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000543 data->info()->is_deoptimization_enabled()
544 ? JSCallReducer::kDeoptimizationEnabled
545 : JSCallReducer::kNoFlags,
546 data->native_context());
547 JSContextSpecialization context_specialization(
548 &graph_reducer, data->jsgraph(),
549 data->info()->is_function_context_specializing()
550 ? data->info()->context()
551 : MaybeHandle<Context>());
552 JSFrameSpecialization frame_specialization(data->info()->osr_frame(),
553 data->jsgraph());
554 JSGlobalObjectSpecialization global_object_specialization(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100555 &graph_reducer, data->jsgraph(), data->native_context(),
556 data->info()->dependencies());
557 JSNativeContextSpecialization::Flags flags =
558 JSNativeContextSpecialization::kNoFlags;
559 if (data->info()->is_bailout_on_uninitialized()) {
560 flags |= JSNativeContextSpecialization::kBailoutOnUninitialized;
561 }
562 if (data->info()->is_deoptimization_enabled()) {
563 flags |= JSNativeContextSpecialization::kDeoptimizationEnabled;
564 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 JSNativeContextSpecialization native_context_specialization(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100566 &graph_reducer, data->jsgraph(), flags, data->native_context(),
567 data->info()->dependencies(), temp_zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 JSInliningHeuristic inlining(&graph_reducer,
569 data->info()->is_inlining_enabled()
570 ? JSInliningHeuristic::kGeneralInlining
571 : JSInliningHeuristic::kRestrictedInlining,
572 temp_zone, data->info(), data->jsgraph());
573 AddReducer(data, &graph_reducer, &dead_code_elimination);
574 AddReducer(data, &graph_reducer, &common_reducer);
575 if (data->info()->is_frame_specializing()) {
576 AddReducer(data, &graph_reducer, &frame_specialization);
577 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100578 if (data->info()->is_deoptimization_enabled()) {
579 AddReducer(data, &graph_reducer, &global_object_specialization);
580 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581 AddReducer(data, &graph_reducer, &native_context_specialization);
582 AddReducer(data, &graph_reducer, &context_specialization);
583 AddReducer(data, &graph_reducer, &call_reducer);
584 AddReducer(data, &graph_reducer, &inlining);
585 graph_reducer.ReduceGraph();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400586 }
587};
588
589
590struct TyperPhase {
591 static const char* phase_name() { return "typer"; }
592
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000593 void Run(PipelineData* data, Zone* temp_zone, Typer* typer) {
594 NodeVector roots(temp_zone);
595 data->jsgraph()->GetCachedNodes(&roots);
596 typer->Run(roots);
597 }
598};
599
600
601struct OsrDeconstructionPhase {
602 static const char* phase_name() { return "OSR deconstruction"; }
603
604 void Run(PipelineData* data, Zone* temp_zone) {
605 OsrHelper osr_helper(data->info());
606 osr_helper.Deconstruct(data->jsgraph(), data->common(), temp_zone);
607 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608};
609
610
611struct TypedLoweringPhase {
612 static const char* phase_name() { return "typed lowering"; }
613
614 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
616 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
617 data->common());
618 LoadElimination load_elimination(&graph_reducer);
619 JSBuiltinReducer builtin_reducer(&graph_reducer, data->jsgraph());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100620 MaybeHandle<LiteralsArray> literals_array =
621 data->info()->is_native_context_specializing()
622 ? handle(data->info()->closure()->literals(), data->isolate())
623 : MaybeHandle<LiteralsArray>();
624 JSCreateLowering create_lowering(
625 &graph_reducer, data->info()->dependencies(), data->jsgraph(),
626 literals_array, temp_zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627 JSTypedLowering::Flags typed_lowering_flags = JSTypedLowering::kNoFlags;
628 if (data->info()->is_deoptimization_enabled()) {
629 typed_lowering_flags |= JSTypedLowering::kDeoptimizationEnabled;
630 }
631 if (data->info()->shared_info()->HasBytecodeArray()) {
632 typed_lowering_flags |= JSTypedLowering::kDisableBinaryOpReduction;
633 }
634 JSTypedLowering typed_lowering(&graph_reducer, data->info()->dependencies(),
635 typed_lowering_flags, data->jsgraph(),
636 temp_zone);
637 JSIntrinsicLowering intrinsic_lowering(
638 &graph_reducer, data->jsgraph(),
639 data->info()->is_deoptimization_enabled()
640 ? JSIntrinsicLowering::kDeoptimizationEnabled
641 : JSIntrinsicLowering::kDeoptimizationDisabled);
642 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
643 data->common(), data->machine());
644 AddReducer(data, &graph_reducer, &dead_code_elimination);
645 AddReducer(data, &graph_reducer, &builtin_reducer);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100646 if (data->info()->is_deoptimization_enabled()) {
647 AddReducer(data, &graph_reducer, &create_lowering);
648 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000649 AddReducer(data, &graph_reducer, &typed_lowering);
650 AddReducer(data, &graph_reducer, &intrinsic_lowering);
651 AddReducer(data, &graph_reducer, &load_elimination);
652 AddReducer(data, &graph_reducer, &common_reducer);
653 graph_reducer.ReduceGraph();
654 }
655};
656
657
658struct BranchEliminationPhase {
659 static const char* phase_name() { return "branch condition elimination"; }
660
661 void Run(PipelineData* data, Zone* temp_zone) {
662 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
663 BranchElimination branch_condition_elimination(&graph_reducer,
664 data->jsgraph(), temp_zone);
665 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
666 data->common());
667 AddReducer(data, &graph_reducer, &branch_condition_elimination);
668 AddReducer(data, &graph_reducer, &dead_code_elimination);
669 graph_reducer.ReduceGraph();
670 }
671};
672
673
674struct EscapeAnalysisPhase {
675 static const char* phase_name() { return "escape analysis"; }
676
677 void Run(PipelineData* data, Zone* temp_zone) {
678 EscapeAnalysis escape_analysis(data->graph(), data->jsgraph()->common(),
679 temp_zone);
680 escape_analysis.Run();
681 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
682 EscapeAnalysisReducer escape_reducer(&graph_reducer, data->jsgraph(),
683 &escape_analysis, temp_zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100684 escape_reducer.SetExistsVirtualAllocate(
685 escape_analysis.ExistsVirtualAllocate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686 AddReducer(data, &graph_reducer, &escape_reducer);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400687 graph_reducer.ReduceGraph();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100688 escape_reducer.VerifyReplacement();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400689 }
690};
691
692
693struct SimplifiedLoweringPhase {
694 static const char* phase_name() { return "simplified lowering"; }
695
696 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 SimplifiedLowering lowering(data->jsgraph(), temp_zone,
698 data->source_positions());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400699 lowering.LowerAllNodes();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100700
701 // TODO(bmeurer): See comment on SimplifiedLowering::abort_compilation_.
702 if (lowering.abort_compilation_) {
703 data->set_compilation_failed();
704 return;
705 }
706
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
708 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
709 data->common());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400710 SimplifiedOperatorReducer simple_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 ValueNumberingReducer value_numbering(temp_zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400712 MachineOperatorReducer machine_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
714 data->common(), data->machine());
715 AddReducer(data, &graph_reducer, &dead_code_elimination);
716 AddReducer(data, &graph_reducer, &simple_reducer);
717 AddReducer(data, &graph_reducer, &value_numbering);
718 AddReducer(data, &graph_reducer, &machine_reducer);
719 AddReducer(data, &graph_reducer, &common_reducer);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400720 graph_reducer.ReduceGraph();
721 }
722};
723
724
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000725struct ControlFlowOptimizationPhase {
726 static const char* phase_name() { return "control flow optimization"; }
727
728 void Run(PipelineData* data, Zone* temp_zone) {
729 ControlFlowOptimizer optimizer(data->graph(), data->common(),
730 data->machine(), temp_zone);
731 optimizer.Optimize();
732 }
733};
734
735
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400736struct ChangeLoweringPhase {
737 static const char* phase_name() { return "change lowering"; }
738
739 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000740 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
741 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
742 data->common());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400743 SimplifiedOperatorReducer simple_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000744 ValueNumberingReducer value_numbering(temp_zone);
745 ChangeLowering lowering(data->jsgraph());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400746 MachineOperatorReducer machine_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
748 data->common(), data->machine());
749 AddReducer(data, &graph_reducer, &dead_code_elimination);
750 AddReducer(data, &graph_reducer, &simple_reducer);
751 AddReducer(data, &graph_reducer, &value_numbering);
752 AddReducer(data, &graph_reducer, &lowering);
753 AddReducer(data, &graph_reducer, &machine_reducer);
754 AddReducer(data, &graph_reducer, &common_reducer);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400755 graph_reducer.ReduceGraph();
756 }
757};
758
759
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000760struct EarlyGraphTrimmingPhase {
761 static const char* phase_name() { return "early graph trimming"; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400762 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 GraphTrimmer trimmer(temp_zone, data->graph());
764 NodeVector roots(temp_zone);
765 data->jsgraph()->GetCachedNodes(&roots);
766 trimmer.TrimGraph(roots.begin(), roots.end());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400767 }
768};
769
770
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000771struct LateGraphTrimmingPhase {
772 static const char* phase_name() { return "late graph trimming"; }
773 void Run(PipelineData* data, Zone* temp_zone) {
774 GraphTrimmer trimmer(temp_zone, data->graph());
775 NodeVector roots(temp_zone);
776 data->jsgraph()->GetCachedNodes(&roots);
777 trimmer.TrimGraph(roots.begin(), roots.end());
778 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400779};
780
781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782struct StressLoopPeelingPhase {
783 static const char* phase_name() { return "stress loop peeling"; }
784
785 void Run(PipelineData* data, Zone* temp_zone) {
786 // Peel the first outer loop for testing.
787 // TODO(titzer): peel all loops? the N'th loop? Innermost loops?
788 LoopTree* loop_tree = LoopFinder::BuildLoopTree(data->graph(), temp_zone);
789 if (loop_tree != nullptr && loop_tree->outer_loops().size() > 0) {
790 LoopPeeler::Peel(data->graph(), data->common(), loop_tree,
791 loop_tree->outer_loops()[0], temp_zone);
792 }
793 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400794};
795
796
797struct GenericLoweringPhase {
798 static const char* phase_name() { return "generic lowering"; }
799
800 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000801 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
803 data->common());
804 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
805 data->common(), data->machine());
806 JSGenericLowering generic_lowering(data->info()->is_typing_enabled(),
807 data->jsgraph());
808 SelectLowering select_lowering(data->jsgraph()->graph(),
809 data->jsgraph()->common());
810 TailCallOptimization tco(data->common(), data->graph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000811 AddReducer(data, &graph_reducer, &dead_code_elimination);
812 AddReducer(data, &graph_reducer, &common_reducer);
813 AddReducer(data, &graph_reducer, &generic_lowering);
814 AddReducer(data, &graph_reducer, &select_lowering);
815 AddReducer(data, &graph_reducer, &tco);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400816 graph_reducer.ReduceGraph();
817 }
818};
819
820
821struct ComputeSchedulePhase {
822 static const char* phase_name() { return "scheduling"; }
823
824 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 Schedule* schedule = Scheduler::ComputeSchedule(
826 temp_zone, data->graph(), data->info()->is_splitting_enabled()
827 ? Scheduler::kSplitNodes
828 : Scheduler::kNoFlags);
829 if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400830 data->set_schedule(schedule);
831 }
832};
833
834
835struct InstructionSelectionPhase {
836 static const char* phase_name() { return "select instructions"; }
837
838 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000839 InstructionSelector selector(
840 temp_zone, data->graph()->NodeCount(), linkage, data->sequence(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100841 data->schedule(), data->source_positions(), data->frame(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842 data->info()->is_source_positions_enabled()
843 ? InstructionSelector::kAllSourcePositions
844 : InstructionSelector::kCallSourcePositions);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400845 selector.SelectInstructions();
846 }
847};
848
849
850struct MeetRegisterConstraintsPhase {
851 static const char* phase_name() { return "meet register constraints"; }
852
853 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000854 ConstraintBuilder builder(data->register_allocation_data());
855 builder.MeetRegisterConstraints();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400856 }
857};
858
859
860struct ResolvePhisPhase {
861 static const char* phase_name() { return "resolve phis"; }
862
863 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000864 ConstraintBuilder builder(data->register_allocation_data());
865 builder.ResolvePhis();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400866 }
867};
868
869
870struct BuildLiveRangesPhase {
871 static const char* phase_name() { return "build live ranges"; }
872
873 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000874 LiveRangeBuilder builder(data->register_allocation_data(), temp_zone);
875 builder.BuildLiveRanges();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400876 }
877};
878
879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880struct SplinterLiveRangesPhase {
881 static const char* phase_name() { return "splinter live ranges"; }
882
883 void Run(PipelineData* data, Zone* temp_zone) {
884 LiveRangeSeparator live_range_splinterer(data->register_allocation_data(),
885 temp_zone);
886 live_range_splinterer.Splinter();
887 }
888};
889
890
891template <typename RegAllocator>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400892struct AllocateGeneralRegistersPhase {
893 static const char* phase_name() { return "allocate general registers"; }
894
895 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 RegAllocator allocator(data->register_allocation_data(), GENERAL_REGISTERS,
897 temp_zone);
898 allocator.AllocateRegisters();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400899 }
900};
901
902
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000903template <typename RegAllocator>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400904struct AllocateDoubleRegistersPhase {
905 static const char* phase_name() { return "allocate double registers"; }
906
907 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000908 RegAllocator allocator(data->register_allocation_data(), DOUBLE_REGISTERS,
909 temp_zone);
910 allocator.AllocateRegisters();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400911 }
912};
913
914
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000915struct MergeSplintersPhase {
916 static const char* phase_name() { return "merge splintered ranges"; }
917 void Run(PipelineData* pipeline_data, Zone* temp_zone) {
918 RegisterAllocationData* data = pipeline_data->register_allocation_data();
919 LiveRangeMerger live_range_merger(data, temp_zone);
920 live_range_merger.Merge();
921 }
922};
923
924
925struct LocateSpillSlotsPhase {
926 static const char* phase_name() { return "locate spill slots"; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400927
928 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 SpillSlotLocator locator(data->register_allocation_data());
930 locator.LocateSpillSlots();
931 }
932};
933
934
935struct AssignSpillSlotsPhase {
936 static const char* phase_name() { return "assign spill slots"; }
937
938 void Run(PipelineData* data, Zone* temp_zone) {
939 OperandAssigner assigner(data->register_allocation_data());
940 assigner.AssignSpillSlots();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400941 }
942};
943
944
945struct CommitAssignmentPhase {
946 static const char* phase_name() { return "commit assignment"; }
947
948 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 OperandAssigner assigner(data->register_allocation_data());
950 assigner.CommitAssignment();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400951 }
952};
953
954
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955struct PopulateReferenceMapsPhase {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400956 static const char* phase_name() { return "populate pointer maps"; }
957
958 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 ReferenceMapPopulator populator(data->register_allocation_data());
960 populator.PopulateReferenceMaps();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400961 }
962};
963
964
965struct ConnectRangesPhase {
966 static const char* phase_name() { return "connect ranges"; }
967
968 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000969 LiveRangeConnector connector(data->register_allocation_data());
970 connector.ConnectRanges(temp_zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400971 }
972};
973
974
975struct ResolveControlFlowPhase {
976 static const char* phase_name() { return "resolve control flow"; }
977
978 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000979 LiveRangeConnector connector(data->register_allocation_data());
980 connector.ResolveControlFlow(temp_zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400981 }
982};
983
984
985struct OptimizeMovesPhase {
986 static const char* phase_name() { return "optimize moves"; }
987
988 void Run(PipelineData* data, Zone* temp_zone) {
989 MoveOptimizer move_optimizer(temp_zone, data->sequence());
990 move_optimizer.Run();
991 }
992};
993
994
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995struct FrameElisionPhase {
996 static const char* phase_name() { return "frame elision"; }
997
998 void Run(PipelineData* data, Zone* temp_zone) {
999 FrameElider(data->sequence()).Run();
1000 }
1001};
1002
1003
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001004struct JumpThreadingPhase {
1005 static const char* phase_name() { return "jump threading"; }
1006
Ben Murdoch097c5b22016-05-18 11:27:45 +01001007 void Run(PipelineData* data, Zone* temp_zone, bool frame_at_start) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 ZoneVector<RpoNumber> result(temp_zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001009 if (JumpThreading::ComputeForwarding(temp_zone, result, data->sequence(),
1010 frame_at_start)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001011 JumpThreading::ApplyForwarding(result, data->sequence());
1012 }
1013 }
1014};
1015
1016
1017struct GenerateCodePhase {
1018 static const char* phase_name() { return "generate code"; }
1019
1020 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
1021 CodeGenerator generator(data->frame(), linkage, data->sequence(),
1022 data->info());
1023 data->set_code(generator.GenerateCode());
1024 }
1025};
1026
1027
1028struct PrintGraphPhase {
1029 static const char* phase_name() { return nullptr; }
1030
1031 void Run(PipelineData* data, Zone* temp_zone, const char* phase) {
1032 CompilationInfo* info = data->info();
1033 Graph* graph = data->graph();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001034
1035 { // Print JSON.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001036 FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "a+");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001037 if (json_file == nullptr) return;
1038 OFStream json_of(json_file);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001039 json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":"
1040 << AsJSON(*graph, data->source_positions()) << "},\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001041 fclose(json_file);
1042 }
1043
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001044 if (FLAG_trace_turbo_graph) { // Simple textual RPO.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 OFStream os(stdout);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001046 os << "-- Graph after " << phase << " -- " << std::endl;
1047 os << AsRPO(*graph);
1048 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001049 }
1050};
1051
1052
1053struct VerifyGraphPhase {
1054 static const char* phase_name() { return nullptr; }
1055
1056 void Run(PipelineData* data, Zone* temp_zone, const bool untyped) {
1057 Verifier::Run(data->graph(), FLAG_turbo_types && !untyped
1058 ? Verifier::TYPED
1059 : Verifier::UNTYPED);
1060 }
1061};
1062
1063
1064void Pipeline::BeginPhaseKind(const char* phase_kind_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001065 if (data_->pipeline_statistics() != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001066 data_->pipeline_statistics()->BeginPhaseKind(phase_kind_name);
1067 }
1068}
1069
1070
1071void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) {
1072 if (FLAG_trace_turbo) {
1073 Run<PrintGraphPhase>(phase);
1074 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075 if (FLAG_turbo_verify) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001076 Run<VerifyGraphPhase>(untyped);
1077 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001078}
1079
1080
1081Handle<Code> Pipeline::GenerateCode() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001082 ZonePool zone_pool;
1083 base::SmartPointer<PipelineStatistics> pipeline_statistics;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001084
1085 if (FLAG_turbo_stats) {
1086 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool));
1087 pipeline_statistics->BeginPhaseKind("initializing");
1088 }
1089
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001090 if (FLAG_trace_turbo) {
1091 FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "w+");
1092 if (json_file != nullptr) {
1093 OFStream json_of(json_file);
1094 Handle<Script> script = info()->script();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001095 base::SmartArrayPointer<char> function_name = info()->GetDebugName();
1096 int pos = info()->shared_info()->start_position();
1097 json_of << "{\"function\":\"" << function_name.get()
1098 << "\", \"sourcePosition\":" << pos << ", \"source\":\"";
Ben Murdoch097c5b22016-05-18 11:27:45 +01001099 if (info()->has_literal() && !script->IsUndefined() &&
1100 !script->source()->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 DisallowHeapAllocation no_allocation;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001102 FunctionLiteral* function = info()->literal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001103 int start = function->start_position();
1104 int len = function->end_position() - start;
1105 String::SubStringRange source(String::cast(script->source()), start,
1106 len);
1107 for (const auto& c : source) {
1108 json_of << AsEscapedUC16ForJSON(c);
1109 }
1110 }
1111 json_of << "\",\n\"phases\":[";
1112 fclose(json_file);
1113 }
1114 }
1115
1116 PipelineData data(&zone_pool, info(), pipeline_statistics.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001117 this->data_ = &data;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001118
1119 BeginPhaseKind("graph creation");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001120
1121 if (FLAG_trace_turbo) {
1122 OFStream os(stdout);
1123 os << "---------------------------------------------------\n"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001124 << "Begin compiling method " << info()->GetDebugName().get()
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001125 << " using Turbofan" << std::endl;
1126 TurboCfgFile tcf(isolate());
1127 tcf << AsC1VCompilation(info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128 }
1129
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001130 data.source_positions()->AddDecorator();
1131
1132 if (FLAG_loop_assignment_analysis) {
1133 Run<LoopAssignmentAnalysisPhase>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001134 }
1135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 if (info()->is_typing_enabled()) {
1137 Run<TypeHintAnalysisPhase>();
1138 }
1139
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001140 Run<GraphBuilderPhase>();
1141 if (data.compilation_failed()) return Handle<Code>::null();
1142 RunPrintAndVerify("Initial untyped", true);
1143
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001144 // Perform OSR deconstruction.
1145 if (info()->is_osr()) {
1146 Run<OsrDeconstructionPhase>();
1147 RunPrintAndVerify("OSR deconstruction", true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001148 }
1149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 // Perform function context specialization and inlining (if enabled).
1151 Run<InliningPhase>();
1152 RunPrintAndVerify("Inlined", true);
1153
1154 // Remove dead->live edges from the graph.
1155 Run<EarlyGraphTrimmingPhase>();
1156 RunPrintAndVerify("Early trimmed", true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001157
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001158 if (FLAG_print_turbo_replay) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001159 // Print a replay of the initial graph.
1160 GraphReplayPrinter::PrintReplay(data.graph());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161 }
1162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001163 base::SmartPointer<Typer> typer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001164 if (info()->is_typing_enabled()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001165 // Type the graph.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166 typer.Reset(new Typer(isolate(), data.graph(),
1167 info()->is_deoptimization_enabled()
1168 ? Typer::kDeoptimizationEnabled
1169 : Typer::kNoFlags,
1170 info()->dependencies()));
1171 Run<TyperPhase>(typer.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001172 RunPrintAndVerify("Typed");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173 }
1174
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001175 BeginPhaseKind("lowering");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001176
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001177 if (info()->is_typing_enabled()) {
1178 // Lower JSOperators where we can determine types.
1179 Run<TypedLoweringPhase>();
1180 RunPrintAndVerify("Lowered typed");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001181
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001182 if (FLAG_turbo_stress_loop_peeling) {
1183 Run<StressLoopPeelingPhase>();
1184 RunPrintAndVerify("Loop peeled");
1185 }
1186
1187 if (FLAG_turbo_escape) {
1188 Run<EscapeAnalysisPhase>();
1189 RunPrintAndVerify("Escape Analysed");
1190 }
1191
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001192 // Lower simplified operators and insert changes.
1193 Run<SimplifiedLoweringPhase>();
1194 RunPrintAndVerify("Lowered simplified");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 Run<BranchEliminationPhase>();
1197 RunPrintAndVerify("Branch conditions eliminated");
1198
1199 // Optimize control flow.
1200 if (FLAG_turbo_cf_optimization) {
1201 Run<ControlFlowOptimizationPhase>();
1202 RunPrintAndVerify("Control flow optimized");
1203 }
1204
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001205 // Lower changes that have been inserted before.
1206 Run<ChangeLoweringPhase>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001207 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001208 RunPrintAndVerify("Lowered changes", true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001209 }
1210
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001211 // Lower any remaining generic JSOperators.
1212 Run<GenericLoweringPhase>();
1213 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
1214 RunPrintAndVerify("Lowered generic", true);
1215
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001216 Run<LateGraphTrimmingPhase>();
1217 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
1218 RunPrintAndVerify("Late trimmed", true);
1219
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001220 BeginPhaseKind("block building");
1221
1222 data.source_positions()->RemoveDecorator();
1223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224 // Kill the Typer and thereby uninstall the decorator (if any).
1225 typer.Reset(nullptr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001226
Ben Murdoch097c5b22016-05-18 11:27:45 +01001227 // TODO(bmeurer): See comment on SimplifiedLowering::abort_compilation_.
1228 if (data.compilation_failed()) return Handle<Code>::null();
1229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 return ScheduleAndGenerateCode(
1231 Linkage::ComputeIncoming(data.instruction_zone(), info()));
1232}
1233
1234
1235Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate,
1236 CallDescriptor* call_descriptor,
1237 Graph* graph, Schedule* schedule,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001238 Code::Flags flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 const char* debug_name) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001240 CompilationInfo info(debug_name, isolate, graph->zone(), flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241
1242 // Construct a pipeline for scheduling and code generation.
1243 ZonePool zone_pool;
1244 PipelineData data(&zone_pool, &info, graph, schedule);
1245 base::SmartPointer<PipelineStatistics> pipeline_statistics;
1246 if (FLAG_turbo_stats) {
1247 pipeline_statistics.Reset(new PipelineStatistics(&info, &zone_pool));
1248 pipeline_statistics->BeginPhaseKind("stub codegen");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001249 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001250
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001251 Pipeline pipeline(&info);
1252 pipeline.data_ = &data;
1253 DCHECK_NOT_NULL(data.schedule());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001254
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001255 if (FLAG_trace_turbo) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001256 FILE* json_file = OpenVisualizerLogFile(&info, nullptr, "json", "w+");
1257 if (json_file != nullptr) {
1258 OFStream json_of(json_file);
1259 json_of << "{\"function\":\"" << info.GetDebugName().get()
1260 << "\", \"source\":\"\",\n\"phases\":[";
1261 fclose(json_file);
1262 }
1263 pipeline.Run<PrintGraphPhase>("Machine");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264 }
1265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001266 return pipeline.ScheduleAndGenerateCode(call_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267}
1268
1269
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001270Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
1271 Graph* graph,
1272 Schedule* schedule) {
1273 CallDescriptor* call_descriptor =
1274 Linkage::ComputeIncoming(info->zone(), info);
1275 return GenerateCodeForTesting(info, call_descriptor, graph, schedule);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276}
1277
1278
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001279Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
1280 CallDescriptor* call_descriptor,
1281 Graph* graph,
1282 Schedule* schedule) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 // Construct a pipeline for scheduling and code generation.
1284 ZonePool zone_pool;
1285 PipelineData data(&zone_pool, info, graph, schedule);
1286 base::SmartPointer<PipelineStatistics> pipeline_statistics;
1287 if (FLAG_turbo_stats) {
1288 pipeline_statistics.Reset(new PipelineStatistics(info, &zone_pool));
1289 pipeline_statistics->BeginPhaseKind("test codegen");
1290 }
1291
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001292 Pipeline pipeline(info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001293 pipeline.data_ = &data;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001294 if (data.schedule() == nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001295 // TODO(rossberg): Should this really be untyped?
1296 pipeline.RunPrintAndVerify("Machine", true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001297 }
1298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001299 return pipeline.ScheduleAndGenerateCode(call_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001300}
1301
1302
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001303bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
1304 InstructionSequence* sequence,
1305 bool run_verifier) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001306 CompilationInfo info("testing", sequence->isolate(), sequence->zone());
1307 ZonePool zone_pool;
1308 PipelineData data(&zone_pool, &info, sequence);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001309 Pipeline pipeline(&info);
1310 pipeline.data_ = &data;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001311 pipeline.data_->InitializeFrameData(nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312 pipeline.AllocateRegisters(config, nullptr, run_verifier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001313 return !data.compilation_failed();
1314}
1315
1316
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001317Handle<Code> Pipeline::ScheduleAndGenerateCode(
1318 CallDescriptor* call_descriptor) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001319 PipelineData* data = this->data_;
1320
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001321 DCHECK_NOT_NULL(data->graph());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001322
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001323 if (data->schedule() == nullptr) Run<ComputeSchedulePhase>();
1324 TraceSchedule(data->info(), data->schedule());
1325
1326 BasicBlockProfiler::Data* profiler_data = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001327 if (FLAG_turbo_profiling) {
1328 profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(),
1329 data->schedule());
1330 }
1331
1332 data->InitializeInstructionSequence();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001333
Ben Murdoch097c5b22016-05-18 11:27:45 +01001334 data->InitializeFrameData(call_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001335 // Select and schedule instructions covering the scheduled graph.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336 Linkage linkage(call_descriptor);
1337 Run<InstructionSelectionPhase>(&linkage);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001338
1339 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
1340 TurboCfgFile tcf(isolate());
1341 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(),
1342 data->sequence());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001343 }
1344
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001345 std::ostringstream source_position_output;
1346 if (FLAG_trace_turbo) {
1347 // Output source position information before the graph is deleted.
1348 data_->source_positions()->Print(source_position_output);
1349 }
1350
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001351 data->DeleteGraphZone();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001353 BeginPhaseKind("register allocation");
1354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001355 bool run_verifier = FLAG_turbo_verify_allocation;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001356
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001357 // Allocate registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001358 AllocateRegisters(
1359 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
1360 call_descriptor, run_verifier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001361 if (data->compilation_failed()) {
1362 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 return Handle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001364 }
1365
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001366 BeginPhaseKind("code generation");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001367 // TODO(mtrofin): move this off to the register allocator.
1368 bool generate_frame_at_start =
1369 !FLAG_turbo_frame_elision || !data_->info()->IsStub() ||
1370 !data_->frame()->needs_frame() ||
1371 data_->sequence()->instruction_blocks().front()->needs_frame() ||
1372 linkage.GetIncomingDescriptor()->CalleeSavedFPRegisters() != 0 ||
1373 linkage.GetIncomingDescriptor()->CalleeSavedRegisters() != 0;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001374 // Optimimize jumps.
1375 if (FLAG_turbo_jt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001376 Run<JumpThreadingPhase>(generate_frame_at_start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001377 }
1378
1379 // Generate final machine code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001380 Run<GenerateCodePhase>(&linkage);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001381
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001382 Handle<Code> code = data->code();
1383 if (profiler_data != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001384#if ENABLE_DISASSEMBLER
1385 std::ostringstream os;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386 code->Disassemble(nullptr, os);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001387 profiler_data->SetCode(&os);
1388#endif
1389 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001390
1391 info()->SetCode(code);
1392 v8::internal::CodeGenerator::PrintCode(code, info());
1393
1394 if (FLAG_trace_turbo) {
1395 FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "a+");
1396 if (json_file != nullptr) {
1397 OFStream json_of(json_file);
1398 json_of
1399 << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
1400#if ENABLE_DISASSEMBLER
1401 std::stringstream disassembly_stream;
1402 code->Disassemble(nullptr, disassembly_stream);
1403 std::string disassembly_string(disassembly_stream.str());
1404 for (const auto& c : disassembly_string) {
1405 json_of << AsEscapedUC16ForJSON(c);
1406 }
1407#endif // ENABLE_DISASSEMBLER
1408 json_of << "\"}\n],\n";
1409 json_of << "\"nodePositions\":";
1410 json_of << source_position_output.str();
1411 json_of << "}";
1412 fclose(json_file);
1413 }
1414 OFStream os(stdout);
1415 os << "---------------------------------------------------\n"
1416 << "Finished compiling method " << info()->GetDebugName().get()
1417 << " using Turbofan" << std::endl;
1418 }
1419
1420 return code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001421}
1422
1423
1424void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001425 CallDescriptor* descriptor,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001426 bool run_verifier) {
1427 PipelineData* data = this->data_;
1428
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001429 // Don't track usage for this zone in compiler stats.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001430 base::SmartPointer<Zone> verifier_zone;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001431 RegisterAllocatorVerifier* verifier = nullptr;
1432 if (run_verifier) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001433 verifier_zone.Reset(new Zone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001434 verifier = new (verifier_zone.get()) RegisterAllocatorVerifier(
1435 verifier_zone.get(), config, data->sequence());
1436 }
1437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438 base::SmartArrayPointer<char> debug_name;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001439#ifdef DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001440 debug_name = info()->GetDebugName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001441#endif
1442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001443 data->InitializeRegisterAllocationData(config, descriptor, debug_name.get());
1444 if (info()->is_osr()) {
1445 OsrHelper osr_helper(info());
1446 osr_helper.SetupFrame(data->frame());
1447 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001448
1449 Run<MeetRegisterConstraintsPhase>();
1450 Run<ResolvePhisPhase>();
1451 Run<BuildLiveRangesPhase>();
1452 if (FLAG_trace_turbo_graph) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001453 OFStream os(stdout);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001454 PrintableInstructionSequence printable = {config, data->sequence()};
1455 os << "----- Instruction sequence before register allocation -----\n"
1456 << printable;
1457 }
1458 if (verifier != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001459 CHECK(!data->register_allocation_data()->ExistsUseWithoutDefinition());
1460 CHECK(data->register_allocation_data()
1461 ->RangesDefinedInDeferredStayInDeferred());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001462 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001463
1464 if (FLAG_turbo_preprocess_ranges) {
1465 Run<SplinterLiveRangesPhase>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001466 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001467
1468 if (FLAG_turbo_greedy_regalloc) {
1469 Run<AllocateGeneralRegistersPhase<GreedyAllocator>>();
1470 Run<AllocateDoubleRegistersPhase<GreedyAllocator>>();
1471 } else {
1472 Run<AllocateGeneralRegistersPhase<LinearScanAllocator>>();
1473 Run<AllocateDoubleRegistersPhase<LinearScanAllocator>>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001474 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001475
1476 if (FLAG_turbo_preprocess_ranges) {
1477 Run<MergeSplintersPhase>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001478 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001479
Ben Murdoch097c5b22016-05-18 11:27:45 +01001480 // We plan to enable frame elision only for stubs and bytecode handlers.
1481 if (FLAG_turbo_frame_elision && info()->IsStub()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001482 Run<LocateSpillSlotsPhase>();
1483 Run<FrameElisionPhase>();
1484 }
1485
1486 Run<AssignSpillSlotsPhase>();
1487
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001488 Run<CommitAssignmentPhase>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001489 Run<PopulateReferenceMapsPhase>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001490 Run<ConnectRangesPhase>();
1491 Run<ResolveControlFlowPhase>();
1492 if (FLAG_turbo_move_optimization) {
1493 Run<OptimizeMovesPhase>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001494 }
1495
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001496 if (FLAG_trace_turbo_graph) {
1497 OFStream os(stdout);
1498 PrintableInstructionSequence printable = {config, data->sequence()};
1499 os << "----- Instruction sequence after register allocation -----\n"
1500 << printable;
1501 }
1502
1503 if (verifier != nullptr) {
1504 verifier->VerifyAssignment();
1505 verifier->VerifyGapMoves();
1506 }
1507
1508 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
1509 TurboCfgFile tcf(data->isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001510 tcf << AsC1VRegisterAllocationData("CodeGen",
1511 data->register_allocation_data());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001512 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001514 data->DeleteRegisterAllocationZone();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001515}
1516
Ben Murdoch097c5b22016-05-18 11:27:45 +01001517Isolate* Pipeline::isolate() const { return info()->isolate(); }
1518
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001519} // namespace compiler
1520} // namespace internal
1521} // namespace v8