blob: 1d7e967cc733efc3939b3652d3a5b58dbcabd8a5 [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
Ben Murdochda12d292016-06-02 14:46:10 +0100270 void InitializeInstructionSequence(const CallDescriptor* descriptor) {
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);
Ben Murdochda12d292016-06-02 14:46:10 +0100277 if (descriptor && descriptor->RequiresFrameAsIncoming()) {
278 sequence_->instruction_blocks()[0]->mark_needs_frame();
279 } else {
280 DCHECK_EQ(0, descriptor->CalleeSavedFPRegisters());
281 DCHECK_EQ(0, descriptor->CalleeSavedRegisters());
282 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400283 }
284
Ben Murdoch097c5b22016-05-18 11:27:45 +0100285 void InitializeFrameData(CallDescriptor* descriptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 DCHECK(frame_ == nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 int fixed_frame_size = 0;
288 if (descriptor != nullptr) {
Ben Murdochda12d292016-06-02 14:46:10 +0100289 fixed_frame_size = CalculateFixedFrameSize(descriptor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 }
291 frame_ = new (instruction_zone()) Frame(fixed_frame_size, descriptor);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100292 }
293
294 void InitializeRegisterAllocationData(const RegisterConfiguration* config,
295 CallDescriptor* descriptor,
296 const char* debug_name) {
297 DCHECK(register_allocation_data_ == nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 register_allocation_data_ = new (register_allocation_zone())
299 RegisterAllocationData(config, register_allocation_zone(), frame(),
300 sequence(), debug_name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301 }
302
303 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400304 Isolate* isolate_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305 CompilationInfo* info_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400306 Zone* outer_zone_;
307 ZonePool* const zone_pool_;
308 PipelineStatistics* pipeline_statistics_;
309 bool compilation_failed_;
310 Handle<Code> code_;
311
312 // All objects in the following group of fields are allocated in graph_zone_.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 // They are all set to nullptr when the graph_zone_ is destroyed.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400314 ZonePool::Scope graph_zone_scope_;
315 Zone* graph_zone_;
316 Graph* graph_;
317 // TODO(dcarney): make this into a ZoneObject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318 base::SmartPointer<SourcePositionTable> source_positions_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400319 LoopAssignmentAnalysis* loop_assignment_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 TypeHintAnalysis* type_hint_analysis_ = nullptr;
321 SimplifiedOperatorBuilder* simplified_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400322 MachineOperatorBuilder* machine_;
323 CommonOperatorBuilder* common_;
324 JSOperatorBuilder* javascript_;
325 JSGraph* jsgraph_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400326 Schedule* schedule_;
327
328 // All objects in the following group of fields are allocated in
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 // instruction_zone_. They are all set to nullptr when the instruction_zone_
330 // is
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400331 // destroyed.
332 ZonePool::Scope instruction_zone_scope_;
333 Zone* instruction_zone_;
334 InstructionSequence* sequence_;
335 Frame* frame_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336
337 // All objects in the following group of fields are allocated in
338 // register_allocation_zone_. They are all set to nullptr when the zone is
339 // destroyed.
340 ZonePool::Scope register_allocation_zone_scope_;
341 Zone* register_allocation_zone_;
342 RegisterAllocationData* register_allocation_data_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400343
Ben Murdochda12d292016-06-02 14:46:10 +0100344 int CalculateFixedFrameSize(CallDescriptor* descriptor) {
345 if (descriptor->IsJSFunctionCall()) {
346 return StandardFrameConstants::kFixedSlotCount;
347 }
348 return descriptor->IsCFunctionCall()
349 ? (CommonFrameConstants::kFixedSlotCountAboveFp +
350 CommonFrameConstants::kCPSlotCount)
351 : TypedFrameConstants::kFixedSlotCount;
352 }
353
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400354 DISALLOW_COPY_AND_ASSIGN(PipelineData);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355};
356
357
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358namespace {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400360struct TurboCfgFile : public std::ofstream {
361 explicit TurboCfgFile(Isolate* isolate)
362 : std::ofstream(isolate->GetTurboCfgFileName().c_str(),
363 std::ios_base::app) {}
364};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400366
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367void TraceSchedule(CompilationInfo* info, Schedule* schedule) {
368 if (FLAG_trace_turbo) {
369 FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "a+");
370 if (json_file != nullptr) {
371 OFStream json_of(json_file);
372 json_of << "{\"name\":\"Schedule\",\"type\":\"schedule\",\"data\":\"";
373 std::stringstream schedule_stream;
374 schedule_stream << *schedule;
375 std::string schedule_string(schedule_stream.str());
376 for (const auto& c : schedule_string) {
377 json_of << AsEscapedUC16ForJSON(c);
378 }
379 json_of << "\"},\n";
380 fclose(json_file);
381 }
382 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400383 if (!FLAG_trace_turbo_graph && !FLAG_trace_turbo_scheduler) return;
384 OFStream os(stdout);
385 os << "-- Schedule --------------------------------------\n" << *schedule;
386}
387
388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389class AstGraphBuilderWithPositions final : public AstGraphBuilder {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400391 AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
392 JSGraph* jsgraph,
393 LoopAssignmentAnalysis* loop_assignment,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394 TypeHintAnalysis* type_hint_analysis,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400395 SourcePositionTable* source_positions)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 : AstGraphBuilder(local_zone, info, jsgraph, loop_assignment,
397 type_hint_analysis),
398 source_positions_(source_positions),
399 start_position_(info->shared_info()->start_position()) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000400
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401 bool CreateGraph(bool stack_check) {
402 SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
403 return AstGraphBuilder::CreateGraph(stack_check);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000404 }
405
406#define DEF_VISIT(type) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407 void Visit##type(type* node) override { \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 SourcePositionTable::Scope pos(source_positions_, \
409 SourcePosition(node->position())); \
410 AstGraphBuilder::Visit##type(node); \
411 }
412 AST_NODE_LIST(DEF_VISIT)
413#undef DEF_VISIT
414
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415 private:
416 SourcePositionTable* const source_positions_;
417 SourcePosition const start_position_;
418};
419
420
421class SourcePositionWrapper final : public Reducer {
422 public:
423 SourcePositionWrapper(Reducer* reducer, SourcePositionTable* table)
424 : reducer_(reducer), table_(table) {}
425 ~SourcePositionWrapper() final {}
426
427 Reduction Reduce(Node* node) final {
428 SourcePosition const pos = table_->GetSourcePosition(node);
429 SourcePositionTable::Scope position(table_, pos);
430 return reducer_->Reduce(node);
431 }
432
433 void Finalize() final { reducer_->Finalize(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400434
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000435 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 Reducer* const reducer_;
437 SourcePositionTable* const table_;
438
439 DISALLOW_COPY_AND_ASSIGN(SourcePositionWrapper);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440};
441
442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000443class JSGraphReducer final : public GraphReducer {
444 public:
445 JSGraphReducer(JSGraph* jsgraph, Zone* zone)
446 : GraphReducer(zone, jsgraph->graph(), jsgraph->Dead()) {}
447 ~JSGraphReducer() final {}
448};
449
450
451void AddReducer(PipelineData* data, GraphReducer* graph_reducer,
452 Reducer* reducer) {
453 if (data->info()->is_source_positions_enabled()) {
454 void* const buffer = data->graph_zone()->New(sizeof(SourcePositionWrapper));
455 SourcePositionWrapper* const wrapper =
456 new (buffer) SourcePositionWrapper(reducer, data->source_positions());
457 graph_reducer->AddReducer(wrapper);
458 } else {
459 graph_reducer->AddReducer(reducer);
460 }
461}
462
463
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400464class PipelineRunScope {
465 public:
466 PipelineRunScope(PipelineData* data, const char* phase_name)
467 : phase_scope_(
468 phase_name == nullptr ? nullptr : data->pipeline_statistics(),
469 phase_name),
470 zone_scope_(data->zone_pool()) {}
471
472 Zone* zone() { return zone_scope_.zone(); }
473
474 private:
475 PhaseScope phase_scope_;
476 ZonePool::Scope zone_scope_;
477};
478
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479} // namespace
480
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400481
482template <typename Phase>
483void Pipeline::Run() {
484 PipelineRunScope scope(this->data_, Phase::phase_name());
485 Phase phase;
486 phase.Run(this->data_, scope.zone());
487}
488
489
490template <typename Phase, typename Arg0>
491void Pipeline::Run(Arg0 arg_0) {
492 PipelineRunScope scope(this->data_, Phase::phase_name());
493 Phase phase;
494 phase.Run(this->data_, scope.zone(), arg_0);
495}
496
497
498struct LoopAssignmentAnalysisPhase {
499 static const char* phase_name() { return "loop assignment analysis"; }
500
501 void Run(PipelineData* data, Zone* temp_zone) {
502 AstLoopAssignmentAnalyzer analyzer(data->graph_zone(), data->info());
503 LoopAssignmentAnalysis* loop_assignment = analyzer.Analyze();
504 data->set_loop_assignment(loop_assignment);
505 }
506};
507
508
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509struct TypeHintAnalysisPhase {
510 static const char* phase_name() { return "type hint analysis"; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400511
512 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 TypeHintAnalyzer analyzer(data->graph_zone());
514 Handle<Code> code(data->info()->shared_info()->code(), data->isolate());
515 TypeHintAnalysis* type_hint_analysis = analyzer.Analyze(code);
516 data->set_type_hint_analysis(type_hint_analysis);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400517 }
518};
519
520
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000521struct GraphBuilderPhase {
522 static const char* phase_name() { return "graph builder"; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400523
524 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 bool stack_check = !data->info()->IsStub();
526 bool succeeded = false;
527
528 if (data->info()->shared_info()->HasBytecodeArray()) {
529 BytecodeGraphBuilder graph_builder(temp_zone, data->info(),
530 data->jsgraph());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100531 succeeded = graph_builder.CreateGraph();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532 } else {
533 AstGraphBuilderWithPositions graph_builder(
534 temp_zone, data->info(), data->jsgraph(), data->loop_assignment(),
535 data->type_hint_analysis(), data->source_positions());
536 succeeded = graph_builder.CreateGraph(stack_check);
537 }
538
539 if (!succeeded) {
540 data->set_compilation_failed();
541 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400542 }
543};
544
545
546struct InliningPhase {
547 static const char* phase_name() { return "inlining"; }
548
549 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
551 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
552 data->common());
553 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
554 data->common(), data->machine());
Ben Murdochda12d292016-06-02 14:46:10 +0100555 JSCallReducer call_reducer(data->jsgraph(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556 data->info()->is_deoptimization_enabled()
557 ? JSCallReducer::kDeoptimizationEnabled
558 : JSCallReducer::kNoFlags,
559 data->native_context());
560 JSContextSpecialization context_specialization(
561 &graph_reducer, data->jsgraph(),
562 data->info()->is_function_context_specializing()
563 ? data->info()->context()
564 : MaybeHandle<Context>());
565 JSFrameSpecialization frame_specialization(data->info()->osr_frame(),
566 data->jsgraph());
567 JSGlobalObjectSpecialization global_object_specialization(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100568 &graph_reducer, data->jsgraph(), data->native_context(),
569 data->info()->dependencies());
570 JSNativeContextSpecialization::Flags flags =
571 JSNativeContextSpecialization::kNoFlags;
572 if (data->info()->is_bailout_on_uninitialized()) {
573 flags |= JSNativeContextSpecialization::kBailoutOnUninitialized;
574 }
575 if (data->info()->is_deoptimization_enabled()) {
576 flags |= JSNativeContextSpecialization::kDeoptimizationEnabled;
577 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 JSNativeContextSpecialization native_context_specialization(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100579 &graph_reducer, data->jsgraph(), flags, data->native_context(),
580 data->info()->dependencies(), temp_zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581 JSInliningHeuristic inlining(&graph_reducer,
582 data->info()->is_inlining_enabled()
583 ? JSInliningHeuristic::kGeneralInlining
584 : JSInliningHeuristic::kRestrictedInlining,
585 temp_zone, data->info(), data->jsgraph());
586 AddReducer(data, &graph_reducer, &dead_code_elimination);
587 AddReducer(data, &graph_reducer, &common_reducer);
588 if (data->info()->is_frame_specializing()) {
589 AddReducer(data, &graph_reducer, &frame_specialization);
590 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100591 if (data->info()->is_deoptimization_enabled()) {
592 AddReducer(data, &graph_reducer, &global_object_specialization);
593 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 AddReducer(data, &graph_reducer, &native_context_specialization);
595 AddReducer(data, &graph_reducer, &context_specialization);
596 AddReducer(data, &graph_reducer, &call_reducer);
597 AddReducer(data, &graph_reducer, &inlining);
598 graph_reducer.ReduceGraph();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400599 }
600};
601
602
603struct TyperPhase {
604 static const char* phase_name() { return "typer"; }
605
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000606 void Run(PipelineData* data, Zone* temp_zone, Typer* typer) {
607 NodeVector roots(temp_zone);
608 data->jsgraph()->GetCachedNodes(&roots);
609 typer->Run(roots);
610 }
611};
612
613
614struct OsrDeconstructionPhase {
615 static const char* phase_name() { return "OSR deconstruction"; }
616
617 void Run(PipelineData* data, Zone* temp_zone) {
618 OsrHelper osr_helper(data->info());
619 osr_helper.Deconstruct(data->jsgraph(), data->common(), temp_zone);
620 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400621};
622
623
624struct TypedLoweringPhase {
625 static const char* phase_name() { return "typed lowering"; }
626
627 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
629 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
630 data->common());
Ben Murdochda12d292016-06-02 14:46:10 +0100631 LoadElimination load_elimination(&graph_reducer, data->graph(),
632 data->common());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 JSBuiltinReducer builtin_reducer(&graph_reducer, data->jsgraph());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100634 MaybeHandle<LiteralsArray> literals_array =
635 data->info()->is_native_context_specializing()
636 ? handle(data->info()->closure()->literals(), data->isolate())
637 : MaybeHandle<LiteralsArray>();
638 JSCreateLowering create_lowering(
639 &graph_reducer, data->info()->dependencies(), data->jsgraph(),
640 literals_array, temp_zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000641 JSTypedLowering::Flags typed_lowering_flags = JSTypedLowering::kNoFlags;
642 if (data->info()->is_deoptimization_enabled()) {
643 typed_lowering_flags |= JSTypedLowering::kDeoptimizationEnabled;
644 }
645 if (data->info()->shared_info()->HasBytecodeArray()) {
646 typed_lowering_flags |= JSTypedLowering::kDisableBinaryOpReduction;
647 }
648 JSTypedLowering typed_lowering(&graph_reducer, data->info()->dependencies(),
649 typed_lowering_flags, data->jsgraph(),
650 temp_zone);
651 JSIntrinsicLowering intrinsic_lowering(
652 &graph_reducer, data->jsgraph(),
653 data->info()->is_deoptimization_enabled()
654 ? JSIntrinsicLowering::kDeoptimizationEnabled
655 : JSIntrinsicLowering::kDeoptimizationDisabled);
Ben Murdochda12d292016-06-02 14:46:10 +0100656 SimplifiedOperatorReducer simple_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
658 data->common(), data->machine());
659 AddReducer(data, &graph_reducer, &dead_code_elimination);
660 AddReducer(data, &graph_reducer, &builtin_reducer);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100661 if (data->info()->is_deoptimization_enabled()) {
662 AddReducer(data, &graph_reducer, &create_lowering);
663 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000664 AddReducer(data, &graph_reducer, &typed_lowering);
665 AddReducer(data, &graph_reducer, &intrinsic_lowering);
666 AddReducer(data, &graph_reducer, &load_elimination);
Ben Murdochda12d292016-06-02 14:46:10 +0100667 AddReducer(data, &graph_reducer, &simple_reducer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 AddReducer(data, &graph_reducer, &common_reducer);
669 graph_reducer.ReduceGraph();
670 }
671};
672
673
674struct BranchEliminationPhase {
675 static const char* phase_name() { return "branch condition elimination"; }
676
677 void Run(PipelineData* data, Zone* temp_zone) {
678 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
679 BranchElimination branch_condition_elimination(&graph_reducer,
680 data->jsgraph(), temp_zone);
681 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
682 data->common());
683 AddReducer(data, &graph_reducer, &branch_condition_elimination);
684 AddReducer(data, &graph_reducer, &dead_code_elimination);
685 graph_reducer.ReduceGraph();
686 }
687};
688
689
690struct EscapeAnalysisPhase {
691 static const char* phase_name() { return "escape analysis"; }
692
693 void Run(PipelineData* data, Zone* temp_zone) {
694 EscapeAnalysis escape_analysis(data->graph(), data->jsgraph()->common(),
695 temp_zone);
696 escape_analysis.Run();
697 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
698 EscapeAnalysisReducer escape_reducer(&graph_reducer, data->jsgraph(),
699 &escape_analysis, temp_zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100700 escape_reducer.SetExistsVirtualAllocate(
701 escape_analysis.ExistsVirtualAllocate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 AddReducer(data, &graph_reducer, &escape_reducer);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 graph_reducer.ReduceGraph();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100704 escape_reducer.VerifyReplacement();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400705 }
706};
707
708
709struct SimplifiedLoweringPhase {
710 static const char* phase_name() { return "simplified lowering"; }
711
712 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 SimplifiedLowering lowering(data->jsgraph(), temp_zone,
714 data->source_positions());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400715 lowering.LowerAllNodes();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100716
717 // TODO(bmeurer): See comment on SimplifiedLowering::abort_compilation_.
718 if (lowering.abort_compilation_) {
719 data->set_compilation_failed();
720 return;
721 }
722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
724 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
725 data->common());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400726 SimplifiedOperatorReducer simple_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727 ValueNumberingReducer value_numbering(temp_zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400728 MachineOperatorReducer machine_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
730 data->common(), data->machine());
731 AddReducer(data, &graph_reducer, &dead_code_elimination);
732 AddReducer(data, &graph_reducer, &simple_reducer);
733 AddReducer(data, &graph_reducer, &value_numbering);
734 AddReducer(data, &graph_reducer, &machine_reducer);
735 AddReducer(data, &graph_reducer, &common_reducer);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400736 graph_reducer.ReduceGraph();
737 }
738};
739
740
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741struct ControlFlowOptimizationPhase {
742 static const char* phase_name() { return "control flow optimization"; }
743
744 void Run(PipelineData* data, Zone* temp_zone) {
745 ControlFlowOptimizer optimizer(data->graph(), data->common(),
746 data->machine(), temp_zone);
747 optimizer.Optimize();
748 }
749};
750
751
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400752struct ChangeLoweringPhase {
753 static const char* phase_name() { return "change lowering"; }
754
755 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
757 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
758 data->common());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400759 SimplifiedOperatorReducer simple_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000760 ValueNumberingReducer value_numbering(temp_zone);
761 ChangeLowering lowering(data->jsgraph());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400762 MachineOperatorReducer machine_reducer(data->jsgraph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
764 data->common(), data->machine());
765 AddReducer(data, &graph_reducer, &dead_code_elimination);
766 AddReducer(data, &graph_reducer, &simple_reducer);
767 AddReducer(data, &graph_reducer, &value_numbering);
768 AddReducer(data, &graph_reducer, &lowering);
769 AddReducer(data, &graph_reducer, &machine_reducer);
770 AddReducer(data, &graph_reducer, &common_reducer);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400771 graph_reducer.ReduceGraph();
772 }
773};
774
775
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000776struct EarlyGraphTrimmingPhase {
777 static const char* phase_name() { return "early graph trimming"; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400778 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000779 GraphTrimmer trimmer(temp_zone, data->graph());
780 NodeVector roots(temp_zone);
781 data->jsgraph()->GetCachedNodes(&roots);
782 trimmer.TrimGraph(roots.begin(), roots.end());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400783 }
784};
785
786
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000787struct LateGraphTrimmingPhase {
788 static const char* phase_name() { return "late graph trimming"; }
789 void Run(PipelineData* data, Zone* temp_zone) {
790 GraphTrimmer trimmer(temp_zone, data->graph());
791 NodeVector roots(temp_zone);
792 data->jsgraph()->GetCachedNodes(&roots);
793 trimmer.TrimGraph(roots.begin(), roots.end());
794 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400795};
796
797
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000798struct StressLoopPeelingPhase {
799 static const char* phase_name() { return "stress loop peeling"; }
800
801 void Run(PipelineData* data, Zone* temp_zone) {
802 // Peel the first outer loop for testing.
803 // TODO(titzer): peel all loops? the N'th loop? Innermost loops?
804 LoopTree* loop_tree = LoopFinder::BuildLoopTree(data->graph(), temp_zone);
805 if (loop_tree != nullptr && loop_tree->outer_loops().size() > 0) {
806 LoopPeeler::Peel(data->graph(), data->common(), loop_tree,
807 loop_tree->outer_loops()[0], temp_zone);
808 }
809 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400810};
811
812
813struct GenericLoweringPhase {
814 static const char* phase_name() { return "generic lowering"; }
815
816 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000817 JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000818 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
819 data->common());
820 CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
821 data->common(), data->machine());
822 JSGenericLowering generic_lowering(data->info()->is_typing_enabled(),
823 data->jsgraph());
824 SelectLowering select_lowering(data->jsgraph()->graph(),
825 data->jsgraph()->common());
826 TailCallOptimization tco(data->common(), data->graph());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000827 AddReducer(data, &graph_reducer, &dead_code_elimination);
828 AddReducer(data, &graph_reducer, &common_reducer);
829 AddReducer(data, &graph_reducer, &generic_lowering);
830 AddReducer(data, &graph_reducer, &select_lowering);
831 AddReducer(data, &graph_reducer, &tco);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400832 graph_reducer.ReduceGraph();
833 }
834};
835
836
837struct ComputeSchedulePhase {
838 static const char* phase_name() { return "scheduling"; }
839
840 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 Schedule* schedule = Scheduler::ComputeSchedule(
842 temp_zone, data->graph(), data->info()->is_splitting_enabled()
843 ? Scheduler::kSplitNodes
844 : Scheduler::kNoFlags);
845 if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400846 data->set_schedule(schedule);
847 }
848};
849
850
851struct InstructionSelectionPhase {
852 static const char* phase_name() { return "select instructions"; }
853
854 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855 InstructionSelector selector(
856 temp_zone, data->graph()->NodeCount(), linkage, data->sequence(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100857 data->schedule(), data->source_positions(), data->frame(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000858 data->info()->is_source_positions_enabled()
859 ? InstructionSelector::kAllSourcePositions
860 : InstructionSelector::kCallSourcePositions);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400861 selector.SelectInstructions();
862 }
863};
864
865
866struct MeetRegisterConstraintsPhase {
867 static const char* phase_name() { return "meet register constraints"; }
868
869 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 ConstraintBuilder builder(data->register_allocation_data());
871 builder.MeetRegisterConstraints();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400872 }
873};
874
875
876struct ResolvePhisPhase {
877 static const char* phase_name() { return "resolve phis"; }
878
879 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 ConstraintBuilder builder(data->register_allocation_data());
881 builder.ResolvePhis();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400882 }
883};
884
885
886struct BuildLiveRangesPhase {
887 static const char* phase_name() { return "build live ranges"; }
888
889 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000890 LiveRangeBuilder builder(data->register_allocation_data(), temp_zone);
891 builder.BuildLiveRanges();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400892 }
893};
894
895
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896struct SplinterLiveRangesPhase {
897 static const char* phase_name() { return "splinter live ranges"; }
898
899 void Run(PipelineData* data, Zone* temp_zone) {
900 LiveRangeSeparator live_range_splinterer(data->register_allocation_data(),
901 temp_zone);
902 live_range_splinterer.Splinter();
903 }
904};
905
906
907template <typename RegAllocator>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400908struct AllocateGeneralRegistersPhase {
909 static const char* phase_name() { return "allocate general registers"; }
910
911 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912 RegAllocator allocator(data->register_allocation_data(), GENERAL_REGISTERS,
913 temp_zone);
914 allocator.AllocateRegisters();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400915 }
916};
917
918
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000919template <typename RegAllocator>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400920struct AllocateDoubleRegistersPhase {
921 static const char* phase_name() { return "allocate double registers"; }
922
923 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000924 RegAllocator allocator(data->register_allocation_data(), DOUBLE_REGISTERS,
925 temp_zone);
926 allocator.AllocateRegisters();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400927 }
928};
929
930
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931struct MergeSplintersPhase {
932 static const char* phase_name() { return "merge splintered ranges"; }
933 void Run(PipelineData* pipeline_data, Zone* temp_zone) {
934 RegisterAllocationData* data = pipeline_data->register_allocation_data();
935 LiveRangeMerger live_range_merger(data, temp_zone);
936 live_range_merger.Merge();
937 }
938};
939
940
941struct LocateSpillSlotsPhase {
942 static const char* phase_name() { return "locate spill slots"; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400943
944 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 SpillSlotLocator locator(data->register_allocation_data());
946 locator.LocateSpillSlots();
947 }
948};
949
950
951struct AssignSpillSlotsPhase {
952 static const char* phase_name() { return "assign spill slots"; }
953
954 void Run(PipelineData* data, Zone* temp_zone) {
955 OperandAssigner assigner(data->register_allocation_data());
956 assigner.AssignSpillSlots();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400957 }
958};
959
960
961struct CommitAssignmentPhase {
962 static const char* phase_name() { return "commit assignment"; }
963
964 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 OperandAssigner assigner(data->register_allocation_data());
966 assigner.CommitAssignment();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400967 }
968};
969
970
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971struct PopulateReferenceMapsPhase {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400972 static const char* phase_name() { return "populate pointer maps"; }
973
974 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000975 ReferenceMapPopulator populator(data->register_allocation_data());
976 populator.PopulateReferenceMaps();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400977 }
978};
979
980
981struct ConnectRangesPhase {
982 static const char* phase_name() { return "connect ranges"; }
983
984 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000985 LiveRangeConnector connector(data->register_allocation_data());
986 connector.ConnectRanges(temp_zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400987 }
988};
989
990
991struct ResolveControlFlowPhase {
992 static const char* phase_name() { return "resolve control flow"; }
993
994 void Run(PipelineData* data, Zone* temp_zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 LiveRangeConnector connector(data->register_allocation_data());
996 connector.ResolveControlFlow(temp_zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400997 }
998};
999
1000
1001struct OptimizeMovesPhase {
1002 static const char* phase_name() { return "optimize moves"; }
1003
1004 void Run(PipelineData* data, Zone* temp_zone) {
1005 MoveOptimizer move_optimizer(temp_zone, data->sequence());
1006 move_optimizer.Run();
1007 }
1008};
1009
1010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011struct FrameElisionPhase {
1012 static const char* phase_name() { return "frame elision"; }
1013
1014 void Run(PipelineData* data, Zone* temp_zone) {
1015 FrameElider(data->sequence()).Run();
1016 }
1017};
1018
1019
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001020struct JumpThreadingPhase {
1021 static const char* phase_name() { return "jump threading"; }
1022
Ben Murdoch097c5b22016-05-18 11:27:45 +01001023 void Run(PipelineData* data, Zone* temp_zone, bool frame_at_start) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001024 ZoneVector<RpoNumber> result(temp_zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001025 if (JumpThreading::ComputeForwarding(temp_zone, result, data->sequence(),
1026 frame_at_start)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001027 JumpThreading::ApplyForwarding(result, data->sequence());
1028 }
1029 }
1030};
1031
1032
1033struct GenerateCodePhase {
1034 static const char* phase_name() { return "generate code"; }
1035
1036 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
1037 CodeGenerator generator(data->frame(), linkage, data->sequence(),
1038 data->info());
1039 data->set_code(generator.GenerateCode());
1040 }
1041};
1042
1043
1044struct PrintGraphPhase {
1045 static const char* phase_name() { return nullptr; }
1046
1047 void Run(PipelineData* data, Zone* temp_zone, const char* phase) {
1048 CompilationInfo* info = data->info();
1049 Graph* graph = data->graph();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001050
1051 { // Print JSON.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "a+");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001053 if (json_file == nullptr) return;
1054 OFStream json_of(json_file);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":"
1056 << AsJSON(*graph, data->source_positions()) << "},\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001057 fclose(json_file);
1058 }
1059
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001060 if (FLAG_trace_turbo_graph) { // Simple textual RPO.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001061 OFStream os(stdout);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001062 os << "-- Graph after " << phase << " -- " << std::endl;
1063 os << AsRPO(*graph);
1064 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001065 }
1066};
1067
1068
1069struct VerifyGraphPhase {
1070 static const char* phase_name() { return nullptr; }
1071
1072 void Run(PipelineData* data, Zone* temp_zone, const bool untyped) {
1073 Verifier::Run(data->graph(), FLAG_turbo_types && !untyped
1074 ? Verifier::TYPED
1075 : Verifier::UNTYPED);
1076 }
1077};
1078
1079
1080void Pipeline::BeginPhaseKind(const char* phase_kind_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001081 if (data_->pipeline_statistics() != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001082 data_->pipeline_statistics()->BeginPhaseKind(phase_kind_name);
1083 }
1084}
1085
1086
1087void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) {
1088 if (FLAG_trace_turbo) {
1089 Run<PrintGraphPhase>(phase);
1090 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001091 if (FLAG_turbo_verify) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001092 Run<VerifyGraphPhase>(untyped);
1093 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094}
1095
1096
1097Handle<Code> Pipeline::GenerateCode() {
Ben Murdochda12d292016-06-02 14:46:10 +01001098 ZonePool zone_pool(isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001099 base::SmartPointer<PipelineStatistics> pipeline_statistics;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001100
1101 if (FLAG_turbo_stats) {
1102 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool));
1103 pipeline_statistics->BeginPhaseKind("initializing");
1104 }
1105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001106 if (FLAG_trace_turbo) {
1107 FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "w+");
1108 if (json_file != nullptr) {
1109 OFStream json_of(json_file);
1110 Handle<Script> script = info()->script();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 base::SmartArrayPointer<char> function_name = info()->GetDebugName();
1112 int pos = info()->shared_info()->start_position();
1113 json_of << "{\"function\":\"" << function_name.get()
1114 << "\", \"sourcePosition\":" << pos << ", \"source\":\"";
Ben Murdoch097c5b22016-05-18 11:27:45 +01001115 if (info()->has_literal() && !script->IsUndefined() &&
1116 !script->source()->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001117 DisallowHeapAllocation no_allocation;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001118 FunctionLiteral* function = info()->literal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001119 int start = function->start_position();
1120 int len = function->end_position() - start;
1121 String::SubStringRange source(String::cast(script->source()), start,
1122 len);
1123 for (const auto& c : source) {
1124 json_of << AsEscapedUC16ForJSON(c);
1125 }
1126 }
1127 json_of << "\",\n\"phases\":[";
1128 fclose(json_file);
1129 }
1130 }
1131
1132 PipelineData data(&zone_pool, info(), pipeline_statistics.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001133 this->data_ = &data;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001134
1135 BeginPhaseKind("graph creation");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001136
1137 if (FLAG_trace_turbo) {
1138 OFStream os(stdout);
1139 os << "---------------------------------------------------\n"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 << "Begin compiling method " << info()->GetDebugName().get()
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001141 << " using Turbofan" << std::endl;
1142 TurboCfgFile tcf(isolate());
1143 tcf << AsC1VCompilation(info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001144 }
1145
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001146 data.source_positions()->AddDecorator();
1147
1148 if (FLAG_loop_assignment_analysis) {
1149 Run<LoopAssignmentAnalysisPhase>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001150 }
1151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001152 if (info()->is_typing_enabled()) {
1153 Run<TypeHintAnalysisPhase>();
1154 }
1155
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001156 Run<GraphBuilderPhase>();
1157 if (data.compilation_failed()) return Handle<Code>::null();
1158 RunPrintAndVerify("Initial untyped", true);
1159
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 // Perform OSR deconstruction.
1161 if (info()->is_osr()) {
1162 Run<OsrDeconstructionPhase>();
1163 RunPrintAndVerify("OSR deconstruction", true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001164 }
1165
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166 // Perform function context specialization and inlining (if enabled).
1167 Run<InliningPhase>();
1168 RunPrintAndVerify("Inlined", true);
1169
1170 // Remove dead->live edges from the graph.
1171 Run<EarlyGraphTrimmingPhase>();
1172 RunPrintAndVerify("Early trimmed", true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174 if (FLAG_print_turbo_replay) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001175 // Print a replay of the initial graph.
1176 GraphReplayPrinter::PrintReplay(data.graph());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177 }
1178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 base::SmartPointer<Typer> typer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 if (info()->is_typing_enabled()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001181 // Type the graph.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001182 typer.Reset(new Typer(isolate(), data.graph(),
1183 info()->is_deoptimization_enabled()
1184 ? Typer::kDeoptimizationEnabled
1185 : Typer::kNoFlags,
1186 info()->dependencies()));
1187 Run<TyperPhase>(typer.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001188 RunPrintAndVerify("Typed");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189 }
1190
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001191 BeginPhaseKind("lowering");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001193 if (info()->is_typing_enabled()) {
1194 // Lower JSOperators where we can determine types.
1195 Run<TypedLoweringPhase>();
1196 RunPrintAndVerify("Lowered typed");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198 if (FLAG_turbo_stress_loop_peeling) {
1199 Run<StressLoopPeelingPhase>();
1200 RunPrintAndVerify("Loop peeled");
1201 }
1202
1203 if (FLAG_turbo_escape) {
1204 Run<EscapeAnalysisPhase>();
1205 RunPrintAndVerify("Escape Analysed");
1206 }
1207
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001208 // Lower simplified operators and insert changes.
1209 Run<SimplifiedLoweringPhase>();
1210 RunPrintAndVerify("Lowered simplified");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001212 Run<BranchEliminationPhase>();
1213 RunPrintAndVerify("Branch conditions eliminated");
1214
1215 // Optimize control flow.
1216 if (FLAG_turbo_cf_optimization) {
1217 Run<ControlFlowOptimizationPhase>();
1218 RunPrintAndVerify("Control flow optimized");
1219 }
1220
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001221 // Lower changes that have been inserted before.
1222 Run<ChangeLoweringPhase>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001223 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001224 RunPrintAndVerify("Lowered changes", true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001225 }
1226
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001227 // Lower any remaining generic JSOperators.
1228 Run<GenericLoweringPhase>();
1229 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
1230 RunPrintAndVerify("Lowered generic", true);
1231
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 Run<LateGraphTrimmingPhase>();
1233 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
1234 RunPrintAndVerify("Late trimmed", true);
1235
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001236 BeginPhaseKind("block building");
1237
1238 data.source_positions()->RemoveDecorator();
1239
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001240 // Kill the Typer and thereby uninstall the decorator (if any).
1241 typer.Reset(nullptr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001242
Ben Murdoch097c5b22016-05-18 11:27:45 +01001243 // TODO(bmeurer): See comment on SimplifiedLowering::abort_compilation_.
1244 if (data.compilation_failed()) return Handle<Code>::null();
1245
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001246 return ScheduleAndGenerateCode(
1247 Linkage::ComputeIncoming(data.instruction_zone(), info()));
1248}
1249
1250
1251Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate,
1252 CallDescriptor* call_descriptor,
1253 Graph* graph, Schedule* schedule,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001254 Code::Flags flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001255 const char* debug_name) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001256 CompilationInfo info(debug_name, isolate, graph->zone(), flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001257
1258 // Construct a pipeline for scheduling and code generation.
Ben Murdochda12d292016-06-02 14:46:10 +01001259 ZonePool zone_pool(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001260 PipelineData data(&zone_pool, &info, graph, schedule);
1261 base::SmartPointer<PipelineStatistics> pipeline_statistics;
1262 if (FLAG_turbo_stats) {
1263 pipeline_statistics.Reset(new PipelineStatistics(&info, &zone_pool));
1264 pipeline_statistics->BeginPhaseKind("stub codegen");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001265 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001266
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001267 Pipeline pipeline(&info);
1268 pipeline.data_ = &data;
1269 DCHECK_NOT_NULL(data.schedule());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001270
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001271 if (FLAG_trace_turbo) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001272 FILE* json_file = OpenVisualizerLogFile(&info, nullptr, "json", "w+");
1273 if (json_file != nullptr) {
1274 OFStream json_of(json_file);
1275 json_of << "{\"function\":\"" << info.GetDebugName().get()
1276 << "\", \"source\":\"\",\n\"phases\":[";
1277 fclose(json_file);
1278 }
1279 pipeline.Run<PrintGraphPhase>("Machine");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001280 }
1281
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282 return pipeline.ScheduleAndGenerateCode(call_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283}
1284
1285
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001286Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
1287 Graph* graph,
1288 Schedule* schedule) {
1289 CallDescriptor* call_descriptor =
1290 Linkage::ComputeIncoming(info->zone(), info);
1291 return GenerateCodeForTesting(info, call_descriptor, graph, schedule);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292}
1293
1294
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001295Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
1296 CallDescriptor* call_descriptor,
1297 Graph* graph,
1298 Schedule* schedule) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001299 // Construct a pipeline for scheduling and code generation.
Ben Murdochda12d292016-06-02 14:46:10 +01001300 ZonePool zone_pool(info->isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001301 PipelineData data(&zone_pool, info, graph, schedule);
1302 base::SmartPointer<PipelineStatistics> pipeline_statistics;
1303 if (FLAG_turbo_stats) {
1304 pipeline_statistics.Reset(new PipelineStatistics(info, &zone_pool));
1305 pipeline_statistics->BeginPhaseKind("test codegen");
1306 }
1307
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001308 Pipeline pipeline(info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001309 pipeline.data_ = &data;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310 if (data.schedule() == nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001311 // TODO(rossberg): Should this really be untyped?
1312 pipeline.RunPrintAndVerify("Machine", true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001313 }
1314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001315 return pipeline.ScheduleAndGenerateCode(call_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001316}
1317
1318
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001319bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
1320 InstructionSequence* sequence,
1321 bool run_verifier) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001322 CompilationInfo info("testing", sequence->isolate(), sequence->zone());
Ben Murdochda12d292016-06-02 14:46:10 +01001323 ZonePool zone_pool(sequence->isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001324 PipelineData data(&zone_pool, &info, sequence);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001325 Pipeline pipeline(&info);
1326 pipeline.data_ = &data;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001327 pipeline.data_->InitializeFrameData(nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328 pipeline.AllocateRegisters(config, nullptr, run_verifier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001329 return !data.compilation_failed();
1330}
1331
1332
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001333Handle<Code> Pipeline::ScheduleAndGenerateCode(
1334 CallDescriptor* call_descriptor) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001335 PipelineData* data = this->data_;
1336
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001337 DCHECK_NOT_NULL(data->graph());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 if (data->schedule() == nullptr) Run<ComputeSchedulePhase>();
1340 TraceSchedule(data->info(), data->schedule());
1341
1342 BasicBlockProfiler::Data* profiler_data = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001343 if (FLAG_turbo_profiling) {
1344 profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(),
1345 data->schedule());
1346 }
1347
Ben Murdochda12d292016-06-02 14:46:10 +01001348 data->InitializeInstructionSequence(call_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001349
Ben Murdoch097c5b22016-05-18 11:27:45 +01001350 data->InitializeFrameData(call_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001351 // Select and schedule instructions covering the scheduled graph.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001352 Linkage linkage(call_descriptor);
1353 Run<InstructionSelectionPhase>(&linkage);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001354
1355 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
1356 TurboCfgFile tcf(isolate());
1357 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(),
1358 data->sequence());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359 }
1360
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001361 std::ostringstream source_position_output;
1362 if (FLAG_trace_turbo) {
1363 // Output source position information before the graph is deleted.
1364 data_->source_positions()->Print(source_position_output);
1365 }
1366
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001367 data->DeleteGraphZone();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001369 BeginPhaseKind("register allocation");
1370
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001371 bool run_verifier = FLAG_turbo_verify_allocation;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001372
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001373 // Allocate registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001374 AllocateRegisters(
1375 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
1376 call_descriptor, run_verifier);
Ben Murdochda12d292016-06-02 14:46:10 +01001377 Run<FrameElisionPhase>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001378 if (data->compilation_failed()) {
1379 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001380 return Handle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381 }
1382
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001383 BeginPhaseKind("code generation");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001384 // TODO(mtrofin): move this off to the register allocator.
1385 bool generate_frame_at_start =
Ben Murdochda12d292016-06-02 14:46:10 +01001386 data_->sequence()->instruction_blocks().front()->must_construct_frame();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001387 // Optimimize jumps.
1388 if (FLAG_turbo_jt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001389 Run<JumpThreadingPhase>(generate_frame_at_start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001390 }
1391
1392 // Generate final machine code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001393 Run<GenerateCodePhase>(&linkage);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001394
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001395 Handle<Code> code = data->code();
1396 if (profiler_data != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001397#if ENABLE_DISASSEMBLER
1398 std::ostringstream os;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 code->Disassemble(nullptr, os);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001400 profiler_data->SetCode(&os);
1401#endif
1402 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001403
1404 info()->SetCode(code);
1405 v8::internal::CodeGenerator::PrintCode(code, info());
1406
1407 if (FLAG_trace_turbo) {
1408 FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "a+");
1409 if (json_file != nullptr) {
1410 OFStream json_of(json_file);
1411 json_of
1412 << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
1413#if ENABLE_DISASSEMBLER
1414 std::stringstream disassembly_stream;
1415 code->Disassemble(nullptr, disassembly_stream);
1416 std::string disassembly_string(disassembly_stream.str());
1417 for (const auto& c : disassembly_string) {
1418 json_of << AsEscapedUC16ForJSON(c);
1419 }
1420#endif // ENABLE_DISASSEMBLER
1421 json_of << "\"}\n],\n";
1422 json_of << "\"nodePositions\":";
1423 json_of << source_position_output.str();
1424 json_of << "}";
1425 fclose(json_file);
1426 }
1427 OFStream os(stdout);
1428 os << "---------------------------------------------------\n"
1429 << "Finished compiling method " << info()->GetDebugName().get()
1430 << " using Turbofan" << std::endl;
1431 }
1432
1433 return code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001434}
1435
1436
1437void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438 CallDescriptor* descriptor,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001439 bool run_verifier) {
1440 PipelineData* data = this->data_;
1441
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001442 // Don't track usage for this zone in compiler stats.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001443 base::SmartPointer<Zone> verifier_zone;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001444 RegisterAllocatorVerifier* verifier = nullptr;
1445 if (run_verifier) {
Ben Murdochda12d292016-06-02 14:46:10 +01001446 verifier_zone.Reset(new Zone(isolate()->allocator()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001447 verifier = new (verifier_zone.get()) RegisterAllocatorVerifier(
1448 verifier_zone.get(), config, data->sequence());
1449 }
1450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001451 base::SmartArrayPointer<char> debug_name;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001452#ifdef DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001453 debug_name = info()->GetDebugName();
Ben Murdochda12d292016-06-02 14:46:10 +01001454 data_->sequence()->ValidateEdgeSplitForm();
1455 data_->sequence()->ValidateDeferredBlockExitPaths();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001456#endif
1457
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001458 data->InitializeRegisterAllocationData(config, descriptor, debug_name.get());
1459 if (info()->is_osr()) {
1460 OsrHelper osr_helper(info());
1461 osr_helper.SetupFrame(data->frame());
1462 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001463
1464 Run<MeetRegisterConstraintsPhase>();
1465 Run<ResolvePhisPhase>();
1466 Run<BuildLiveRangesPhase>();
1467 if (FLAG_trace_turbo_graph) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001468 OFStream os(stdout);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001469 PrintableInstructionSequence printable = {config, data->sequence()};
1470 os << "----- Instruction sequence before register allocation -----\n"
1471 << printable;
1472 }
1473 if (verifier != nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001474 CHECK(!data->register_allocation_data()->ExistsUseWithoutDefinition());
1475 CHECK(data->register_allocation_data()
1476 ->RangesDefinedInDeferredStayInDeferred());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001477 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001478
1479 if (FLAG_turbo_preprocess_ranges) {
1480 Run<SplinterLiveRangesPhase>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001481 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001482
1483 if (FLAG_turbo_greedy_regalloc) {
1484 Run<AllocateGeneralRegistersPhase<GreedyAllocator>>();
1485 Run<AllocateDoubleRegistersPhase<GreedyAllocator>>();
1486 } else {
1487 Run<AllocateGeneralRegistersPhase<LinearScanAllocator>>();
1488 Run<AllocateDoubleRegistersPhase<LinearScanAllocator>>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001489 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490
1491 if (FLAG_turbo_preprocess_ranges) {
1492 Run<MergeSplintersPhase>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001493 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001495 Run<AssignSpillSlotsPhase>();
1496
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001497 Run<CommitAssignmentPhase>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001498 Run<PopulateReferenceMapsPhase>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001499 Run<ConnectRangesPhase>();
1500 Run<ResolveControlFlowPhase>();
1501 if (FLAG_turbo_move_optimization) {
1502 Run<OptimizeMovesPhase>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 }
1504
Ben Murdochda12d292016-06-02 14:46:10 +01001505 Run<LocateSpillSlotsPhase>();
1506
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001507 if (FLAG_trace_turbo_graph) {
1508 OFStream os(stdout);
1509 PrintableInstructionSequence printable = {config, data->sequence()};
1510 os << "----- Instruction sequence after register allocation -----\n"
1511 << printable;
1512 }
1513
1514 if (verifier != nullptr) {
1515 verifier->VerifyAssignment();
1516 verifier->VerifyGapMoves();
1517 }
1518
1519 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
1520 TurboCfgFile tcf(data->isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001521 tcf << AsC1VRegisterAllocationData("CodeGen",
1522 data->register_allocation_data());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001523 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001525 data->DeleteRegisterAllocationZone();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526}
1527
Ben Murdoch097c5b22016-05-18 11:27:45 +01001528Isolate* Pipeline::isolate() const { return info()->isolate(); }
1529
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001530} // namespace compiler
1531} // namespace internal
1532} // namespace v8