OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/pipeline.h" | 5 #include "src/compiler/pipeline.h" |
6 | 6 |
7 #include <fstream> // NOLINT(readability/streams) | 7 #include <fstream> // NOLINT(readability/streams) |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/base/platform/elapsed-timer.h" | 10 #include "src/base/platform/elapsed-timer.h" |
(...skipping 25 matching lines...) Expand all Loading... | |
36 #include "src/compiler/zone-pool.h" | 36 #include "src/compiler/zone-pool.h" |
37 #include "src/ostreams.h" | 37 #include "src/ostreams.h" |
38 #include "src/utils.h" | 38 #include "src/utils.h" |
39 | 39 |
40 namespace v8 { | 40 namespace v8 { |
41 namespace internal { | 41 namespace internal { |
42 namespace compiler { | 42 namespace compiler { |
43 | 43 |
44 class PipelineData { | 44 class PipelineData { |
45 public: | 45 public: |
46 explicit PipelineData(CompilationInfo* info, ZonePool* zone_pool, | 46 PipelineData(CompilationInfo* info, ZonePool* zone_pool, |
47 PipelineStatistics* pipeline_statistics) | 47 PipelineStatistics* pipeline_statistics) |
48 : isolate_(info->zone()->isolate()), | 48 : isolate_(info->zone()->isolate()), |
49 info_(info), | |
49 outer_zone_(info->zone()), | 50 outer_zone_(info->zone()), |
50 zone_pool_(zone_pool), | 51 zone_pool_(zone_pool), |
51 pipeline_statistics_(pipeline_statistics), | 52 pipeline_statistics_(pipeline_statistics), |
53 compilation_failed_(false), | |
54 code_(Handle<Code>::null()), | |
52 graph_zone_scope_(zone_pool_), | 55 graph_zone_scope_(zone_pool_), |
53 graph_zone_(graph_zone_scope_.zone()), | 56 graph_zone_(graph_zone_scope_.zone()), |
54 graph_(new (graph_zone()) Graph(graph_zone())), | 57 graph_(new (graph_zone()) Graph(graph_zone())), |
55 source_positions_(new SourcePositionTable(graph())), | 58 source_positions_(new SourcePositionTable(graph())), |
56 machine_(new (graph_zone()) MachineOperatorBuilder( | 59 machine_(new (graph_zone()) MachineOperatorBuilder( |
57 graph_zone(), kMachPtr, | 60 graph_zone(), kMachPtr, |
58 InstructionSelector::SupportedMachineOperatorFlags())), | 61 InstructionSelector::SupportedMachineOperatorFlags())), |
59 common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())), | 62 common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())), |
60 javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())), | 63 javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())), |
61 jsgraph_(new (graph_zone()) | 64 jsgraph_(new (graph_zone()) |
62 JSGraph(graph(), common(), javascript(), machine())), | 65 JSGraph(graph(), common(), javascript(), machine())), |
63 typer_(new Typer(graph(), info->context())), | 66 typer_(new Typer(graph(), info->context())), |
64 schedule_(NULL), | 67 context_node_(nullptr), |
68 schedule_(nullptr), | |
65 instruction_zone_scope_(zone_pool_), | 69 instruction_zone_scope_(zone_pool_), |
66 instruction_zone_(instruction_zone_scope_.zone()) {} | 70 instruction_zone_(instruction_zone_scope_.zone()), |
71 sequence_(nullptr), | |
72 frame_(nullptr) {} | |
73 | |
67 | 74 |
68 // For machine graph testing only. | 75 // For machine graph testing only. |
69 PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool) | 76 PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool) |
70 : isolate_(graph->zone()->isolate()), | 77 : isolate_(graph->zone()->isolate()), |
71 outer_zone_(NULL), | 78 info_(nullptr), |
79 outer_zone_(nullptr), | |
72 zone_pool_(zone_pool), | 80 zone_pool_(zone_pool), |
73 pipeline_statistics_(NULL), | 81 pipeline_statistics_(nullptr), |
82 compilation_failed_(false), | |
83 code_(Handle<Code>::null()), | |
74 graph_zone_scope_(zone_pool_), | 84 graph_zone_scope_(zone_pool_), |
75 graph_zone_(NULL), | 85 graph_zone_(nullptr), |
76 graph_(graph), | 86 graph_(graph), |
77 source_positions_(new SourcePositionTable(graph)), | 87 source_positions_(new SourcePositionTable(graph)), |
78 machine_(NULL), | 88 machine_(nullptr), |
79 common_(NULL), | 89 common_(nullptr), |
80 javascript_(NULL), | 90 javascript_(nullptr), |
81 jsgraph_(NULL), | 91 jsgraph_(nullptr), |
82 typer_(NULL), | 92 typer_(nullptr), |
93 context_node_(nullptr), | |
83 schedule_(schedule), | 94 schedule_(schedule), |
84 instruction_zone_scope_(zone_pool_), | 95 instruction_zone_scope_(zone_pool_), |
85 instruction_zone_(instruction_zone_scope_.zone()) {} | 96 instruction_zone_(instruction_zone_scope_.zone()), |
97 sequence_(nullptr), | |
98 frame_(nullptr) {} | |
86 | 99 |
87 ~PipelineData() { | 100 ~PipelineData() { |
88 DeleteInstructionZone(); | 101 DeleteInstructionZone(); |
89 DeleteGraphZone(); | 102 DeleteGraphZone(); |
90 } | 103 } |
91 | 104 |
92 Isolate* isolate() const { return isolate_; } | 105 Isolate* isolate() const { return isolate_; } |
106 CompilationInfo* info() const { return info_; } | |
93 ZonePool* zone_pool() const { return zone_pool_; } | 107 ZonePool* zone_pool() const { return zone_pool_; } |
94 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } | 108 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } |
109 bool compilation_failed() const { return compilation_failed_; } | |
110 void set_compilation_failed() { compilation_failed_ = true; } | |
111 Handle<Code> code() { return code_; } | |
112 void set_code(Handle<Code> code) { | |
113 DCHECK(code_.is_null()); | |
114 code_ = code; | |
115 } | |
116 | |
117 // RawMachineAssembler generally produces graphs which cannot be verified. | |
118 bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } | |
95 | 119 |
96 Zone* graph_zone() const { return graph_zone_; } | 120 Zone* graph_zone() const { return graph_zone_; } |
97 Graph* graph() const { return graph_; } | 121 Graph* graph() const { return graph_; } |
98 SourcePositionTable* source_positions() const { | 122 SourcePositionTable* source_positions() const { |
99 return source_positions_.get(); | 123 return source_positions_.get(); |
100 } | 124 } |
101 MachineOperatorBuilder* machine() const { return machine_; } | 125 MachineOperatorBuilder* machine() const { return machine_; } |
102 CommonOperatorBuilder* common() const { return common_; } | 126 CommonOperatorBuilder* common() const { return common_; } |
103 JSOperatorBuilder* javascript() const { return javascript_; } | 127 JSOperatorBuilder* javascript() const { return javascript_; } |
104 JSGraph* jsgraph() const { return jsgraph_; } | 128 JSGraph* jsgraph() const { return jsgraph_; } |
105 Typer* typer() const { return typer_.get(); } | 129 Typer* typer() const { return typer_.get(); } |
130 | |
131 Node* context_node() const { return context_node_; } | |
132 void set_context_node(Node* context_node) { | |
133 DCHECK_EQ(nullptr, context_node_); | |
134 context_node_ = context_node; | |
135 } | |
136 | |
106 Schedule* schedule() const { return schedule_; } | 137 Schedule* schedule() const { return schedule_; } |
107 void set_schedule(Schedule* schedule) { | 138 void set_schedule(Schedule* schedule) { |
108 DCHECK_EQ(NULL, schedule_); | 139 DCHECK_EQ(nullptr, schedule_); |
109 schedule_ = schedule; | 140 schedule_ = schedule; |
110 } | 141 } |
111 | 142 |
112 Zone* instruction_zone() const { return instruction_zone_; } | 143 Zone* instruction_zone() const { return instruction_zone_; } |
113 // RawMachineAssembler generally produces graphs which cannot be verified. | 144 InstructionSequence* sequence() const { return sequence_; } |
114 bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } | 145 void set_sequence(InstructionSequence* sequence) { |
146 DCHECK_EQ(nullptr, sequence_); | |
147 sequence_ = sequence; | |
148 } | |
149 Frame* frame() const { return frame_; } | |
150 void set_frame(Frame* frame) { | |
151 DCHECK_EQ(nullptr, frame_); | |
152 frame_ = frame; | |
153 } | |
115 | 154 |
116 void DeleteGraphZone() { | 155 void DeleteGraphZone() { |
117 // Destroy objects with destructors first. | 156 // Destroy objects with destructors first. |
118 source_positions_.Reset(NULL); | 157 source_positions_.Reset(nullptr); |
119 typer_.Reset(NULL); | 158 typer_.Reset(nullptr); |
120 if (graph_zone_ == NULL) return; | 159 if (graph_zone_ == nullptr) return; |
121 // Destroy zone and clear pointers. | 160 // Destroy zone and clear pointers. |
122 graph_zone_scope_.Destroy(); | 161 graph_zone_scope_.Destroy(); |
123 graph_zone_ = NULL; | 162 graph_zone_ = nullptr; |
124 graph_ = NULL; | 163 graph_ = nullptr; |
125 machine_ = NULL; | 164 machine_ = nullptr; |
126 common_ = NULL; | 165 common_ = nullptr; |
127 javascript_ = NULL; | 166 javascript_ = nullptr; |
128 jsgraph_ = NULL; | 167 jsgraph_ = nullptr; |
129 schedule_ = NULL; | 168 context_node_ = nullptr; |
169 schedule_ = nullptr; | |
130 } | 170 } |
131 | 171 |
132 void DeleteInstructionZone() { | 172 void DeleteInstructionZone() { |
133 if (instruction_zone_ == NULL) return; | 173 if (instruction_zone_ == nullptr) return; |
134 instruction_zone_scope_.Destroy(); | 174 instruction_zone_scope_.Destroy(); |
135 instruction_zone_ = NULL; | 175 instruction_zone_ = nullptr; |
176 sequence_ = nullptr; | |
177 frame_ = nullptr; | |
136 } | 178 } |
137 | 179 |
138 private: | 180 private: |
139 Isolate* isolate_; | 181 Isolate* isolate_; |
182 CompilationInfo* info_; | |
140 Zone* outer_zone_; | 183 Zone* outer_zone_; |
141 ZonePool* zone_pool_; | 184 ZonePool* zone_pool_; |
142 PipelineStatistics* pipeline_statistics_; | 185 PipelineStatistics* pipeline_statistics_; |
186 bool compilation_failed_; | |
187 Handle<Code> code_; | |
143 | 188 |
144 ZonePool::Scope graph_zone_scope_; | 189 ZonePool::Scope graph_zone_scope_; |
145 Zone* graph_zone_; | 190 Zone* graph_zone_; |
146 // All objects in the following group of fields are allocated in graph_zone_. | 191 // All objects in the following group of fields are allocated in graph_zone_. |
147 // They are all set to NULL when the graph_zone_ is destroyed. | 192 // They are all set to NULL when the graph_zone_ is destroyed. |
148 Graph* graph_; | 193 Graph* graph_; |
149 // TODO(dcarney): make this into a ZoneObject. | 194 // TODO(dcarney): make this into a ZoneObject. |
150 SmartPointer<SourcePositionTable> source_positions_; | 195 SmartPointer<SourcePositionTable> source_positions_; |
151 MachineOperatorBuilder* machine_; | 196 MachineOperatorBuilder* machine_; |
152 CommonOperatorBuilder* common_; | 197 CommonOperatorBuilder* common_; |
153 JSOperatorBuilder* javascript_; | 198 JSOperatorBuilder* javascript_; |
154 JSGraph* jsgraph_; | 199 JSGraph* jsgraph_; |
155 // TODO(dcarney): make this into a ZoneObject. | 200 // TODO(dcarney): make this into a ZoneObject. |
156 SmartPointer<Typer> typer_; | 201 SmartPointer<Typer> typer_; |
202 Node* context_node_; | |
157 Schedule* schedule_; | 203 Schedule* schedule_; |
158 | 204 |
159 // All objects in the following group of fields are allocated in | 205 // All objects in the following group of fields are allocated in |
160 // instruction_zone_. They are all set to NULL when the instruction_zone_ is | 206 // instruction_zone_. They are all set to NULL when the instruction_zone_ is |
161 // destroyed. | 207 // destroyed. |
162 ZonePool::Scope instruction_zone_scope_; | 208 ZonePool::Scope instruction_zone_scope_; |
163 Zone* instruction_zone_; | 209 Zone* instruction_zone_; |
210 InstructionSequence* sequence_; | |
211 Frame* frame_; | |
164 | 212 |
165 DISALLOW_COPY_AND_ASSIGN(PipelineData); | 213 DISALLOW_COPY_AND_ASSIGN(PipelineData); |
166 }; | 214 }; |
167 | 215 |
168 | 216 |
169 static inline bool VerifyGraphs() { | 217 static inline bool VerifyGraphs() { |
170 #ifdef DEBUG | 218 #ifdef DEBUG |
171 return true; | 219 return true; |
172 #else | 220 #else |
173 return FLAG_turbo_verify; | 221 return FLAG_turbo_verify; |
174 #endif | 222 #endif |
175 } | 223 } |
176 | 224 |
177 | 225 |
178 struct TurboCfgFile : public std::ofstream { | 226 struct TurboCfgFile : public std::ofstream { |
179 explicit TurboCfgFile(Isolate* isolate) | 227 explicit TurboCfgFile(Isolate* isolate) |
180 : std::ofstream(isolate->GetTurboCfgFileName().c_str(), | 228 : std::ofstream(isolate->GetTurboCfgFileName().c_str(), |
181 std::ios_base::app) {} | 229 std::ios_base::app) {} |
182 }; | 230 }; |
183 | 231 |
184 | 232 |
185 void Pipeline::VerifyAndPrintGraph( | 233 static void TraceSchedule(Schedule* schedule) { |
186 Graph* graph, const char* phase, bool untyped) { | 234 if (!FLAG_trace_turbo) return; |
187 if (FLAG_trace_turbo) { | 235 OFStream os(stdout); |
236 os << "-- Schedule --------------------------------------\n" << *schedule; | |
237 } | |
238 | |
239 | |
240 static SmartArrayPointer<char> GetDebugName(CompilationInfo* info) { | |
241 SmartArrayPointer<char> name; | |
242 if (info->IsStub()) { | |
243 if (info->code_stub() != NULL) { | |
244 CodeStub::Major major_key = info->code_stub()->MajorKey(); | |
245 const char* major_name = CodeStub::MajorName(major_key, false); | |
246 size_t len = strlen(major_name); | |
247 name.Reset(new char[len]); | |
248 memcpy(name.get(), major_name, len); | |
249 } | |
250 } else { | |
251 AllowHandleDereference allow_deref; | |
252 name = info->function()->debug_name()->ToCString(); | |
253 } | |
254 return name; | |
255 } | |
256 | |
257 | |
258 class AstGraphBuilderWithPositions : public AstGraphBuilder { | |
259 public: | |
260 explicit AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info, | |
261 JSGraph* jsgraph, | |
262 SourcePositionTable* source_positions) | |
263 : AstGraphBuilder(local_zone, info, jsgraph), | |
264 source_positions_(source_positions) {} | |
265 | |
266 bool CreateGraph() { | |
267 SourcePositionTable::Scope pos(source_positions_, | |
268 SourcePosition::Unknown()); | |
269 return AstGraphBuilder::CreateGraph(); | |
270 } | |
271 | |
272 #define DEF_VISIT(type) \ | |
273 virtual void Visit##type(type* node) OVERRIDE { \ | |
274 SourcePositionTable::Scope pos(source_positions_, \ | |
275 SourcePosition(node->position())); \ | |
276 AstGraphBuilder::Visit##type(node); \ | |
277 } | |
278 AST_NODE_LIST(DEF_VISIT) | |
279 #undef DEF_VISIT | |
280 | |
281 Node* GetFunctionContext() { return AstGraphBuilder::GetFunctionContext(); } | |
282 | |
283 private: | |
284 SourcePositionTable* source_positions_; | |
285 }; | |
286 | |
287 | |
288 class PipelineRunScope { | |
289 public: | |
290 PipelineRunScope(PipelineData* data, const char* phase_name) | |
291 : phase_scope_( | |
292 phase_name == nullptr ? nullptr : data->pipeline_statistics(), | |
293 phase_name), | |
294 zone_scope_(data->zone_pool()) {} | |
295 | |
296 Zone* zone() { return zone_scope_.zone(); } | |
297 | |
298 private: | |
299 PhaseScope phase_scope_; | |
300 ZonePool::Scope zone_scope_; | |
301 }; | |
302 | |
303 | |
304 template <typename Phase> | |
305 void Pipeline::Run() { | |
306 PipelineRunScope scope(this->data_, Phase::phase_name()); | |
307 Phase phase; | |
308 phase.Run(this->data_, scope.zone()); | |
309 } | |
310 | |
311 | |
312 template <typename Phase, typename Arg0> | |
313 void Pipeline::Run(Arg0 arg_0) { | |
314 PipelineRunScope scope(this->data_, Phase::phase_name()); | |
315 Phase phase; | |
316 phase.Run(this->data_, scope.zone(), arg_0); | |
317 } | |
318 | |
319 | |
320 // TODO(dcarney): this one should be unecessary. | |
321 template <typename Phase, typename Arg0, typename Arg1> | |
322 void Pipeline::Run(Arg0 arg_0, Arg1 arg_1) { | |
323 PipelineRunScope scope(this->data_, Phase::phase_name()); | |
324 Phase phase; | |
325 phase.Run(this->data_, scope.zone(), arg_0, arg_1); | |
326 } | |
327 | |
328 | |
329 struct GraphBuilderPhase { | |
330 static const char* phase_name() { return "graph builder"; } | |
titzer
2014/11/14 16:07:47
You can just make these static fields.
| |
331 | |
332 void Run(PipelineData* data, Zone* temp_zone) { | |
333 AstGraphBuilderWithPositions graph_builder( | |
334 temp_zone, data->info(), data->jsgraph(), data->source_positions()); | |
335 if (graph_builder.CreateGraph()) { | |
336 data->set_context_node(graph_builder.GetFunctionContext()); | |
337 } else { | |
338 data->set_compilation_failed(); | |
339 } | |
340 } | |
341 }; | |
342 | |
343 | |
344 struct ContextSpecializerPhase { | |
345 static const char* phase_name() { return nullptr; } | |
346 | |
347 void Run(PipelineData* data, Zone* temp_zone) { | |
348 SourcePositionTable::Scope pos(data->source_positions(), | |
349 SourcePosition::Unknown()); | |
350 JSContextSpecializer spec(data->info(), data->jsgraph(), | |
351 data->context_node()); | |
352 spec.SpecializeToContext(); | |
353 } | |
354 }; | |
355 | |
356 | |
357 struct InliningPhase { | |
358 static const char* phase_name() { return "inlining"; } | |
359 | |
360 void Run(PipelineData* data, Zone* temp_zone) { | |
361 SourcePositionTable::Scope pos(data->source_positions(), | |
362 SourcePosition::Unknown()); | |
363 JSInliner inliner(temp_zone, data->info(), data->jsgraph()); | |
364 inliner.Inline(); | |
365 } | |
366 }; | |
367 | |
368 | |
369 struct TyperPhase { | |
370 static const char* phase_name() { return "typer"; } | |
371 | |
372 void Run(PipelineData* data, Zone* temp_zone) { data->typer()->Run(); } | |
373 }; | |
374 | |
375 | |
376 struct TypedLoweringPhase { | |
377 static const char* phase_name() { return "typed lowering"; } | |
378 | |
379 void Run(PipelineData* data, Zone* temp_zone) { | |
380 SourcePositionTable::Scope pos(data->source_positions(), | |
381 SourcePosition::Unknown()); | |
382 ValueNumberingReducer vn_reducer(data->graph_zone()); | |
383 JSTypedLowering lowering(data->jsgraph()); | |
384 SimplifiedOperatorReducer simple_reducer(data->jsgraph()); | |
385 GraphReducer graph_reducer(data->graph()); | |
386 graph_reducer.AddReducer(&vn_reducer); | |
387 graph_reducer.AddReducer(&lowering); | |
388 graph_reducer.AddReducer(&simple_reducer); | |
389 graph_reducer.ReduceGraph(); | |
390 } | |
391 }; | |
392 | |
393 | |
394 struct SimplifiedLoweringPhase { | |
395 static const char* phase_name() { return "simplified lowering"; } | |
396 | |
397 void Run(PipelineData* data, Zone* temp_zone) { | |
398 SourcePositionTable::Scope pos(data->source_positions(), | |
399 SourcePosition::Unknown()); | |
400 SimplifiedLowering lowering(data->jsgraph()); | |
401 lowering.LowerAllNodes(); | |
402 ValueNumberingReducer vn_reducer(data->graph_zone()); | |
403 SimplifiedOperatorReducer simple_reducer(data->jsgraph()); | |
404 GraphReducer graph_reducer(data->graph()); | |
405 graph_reducer.AddReducer(&vn_reducer); | |
406 graph_reducer.AddReducer(&simple_reducer); | |
407 graph_reducer.ReduceGraph(); | |
408 } | |
409 }; | |
410 | |
411 | |
412 struct ChangeLoweringPhase { | |
413 static const char* phase_name() { return "change lowering"; } | |
414 | |
415 void Run(PipelineData* data, Zone* temp_zone) { | |
416 SourcePositionTable::Scope pos(data->source_positions(), | |
417 SourcePosition::Unknown()); | |
418 Linkage linkage(data->graph_zone(), data->info()); | |
419 ValueNumberingReducer vn_reducer(data->graph_zone()); | |
420 SimplifiedOperatorReducer simple_reducer(data->jsgraph()); | |
421 ChangeLowering lowering(data->jsgraph(), &linkage); | |
422 MachineOperatorReducer mach_reducer(data->jsgraph()); | |
423 GraphReducer graph_reducer(data->graph()); | |
424 // TODO(titzer): Figure out if we should run all reducers at once here. | |
425 graph_reducer.AddReducer(&vn_reducer); | |
426 graph_reducer.AddReducer(&simple_reducer); | |
427 graph_reducer.AddReducer(&lowering); | |
428 graph_reducer.AddReducer(&mach_reducer); | |
429 graph_reducer.ReduceGraph(); | |
430 } | |
431 }; | |
432 | |
433 | |
434 struct ControlReductionPhase { | |
435 void Run(PipelineData* data, Zone* temp_zone) { | |
436 SourcePositionTable::Scope pos(data->source_positions(), | |
437 SourcePosition::Unknown()); | |
438 ControlReducer::ReduceGraph(temp_zone, data->jsgraph(), data->common()); | |
439 } | |
440 }; | |
441 | |
442 | |
443 struct EarlyControlReductionPhase : ControlReductionPhase { | |
444 static const char* phase_name() { return "early control reduction"; } | |
445 }; | |
446 | |
447 | |
448 struct LateControlReductionPhase : ControlReductionPhase { | |
449 static const char* phase_name() { return "late control reduction"; } | |
450 }; | |
451 | |
452 | |
453 struct GenericLoweringPhase { | |
454 static const char* phase_name() { return "generic lowering"; } | |
455 | |
456 void Run(PipelineData* data, Zone* temp_zone) { | |
457 SourcePositionTable::Scope pos(data->source_positions(), | |
458 SourcePosition::Unknown()); | |
459 JSGenericLowering generic(data->info(), data->jsgraph()); | |
460 SelectLowering select(data->jsgraph()->graph(), data->jsgraph()->common()); | |
461 GraphReducer graph_reducer(data->graph()); | |
462 graph_reducer.AddReducer(&generic); | |
463 graph_reducer.AddReducer(&select); | |
464 graph_reducer.ReduceGraph(); | |
465 } | |
466 }; | |
467 | |
468 | |
469 struct ComputeSchedulePhase { | |
470 static const char* phase_name() { return "scheduling"; } | |
471 | |
472 void Run(PipelineData* data, Zone* temp_zone) { | |
473 Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph()); | |
474 TraceSchedule(schedule); | |
475 if (VerifyGraphs()) ScheduleVerifier::Run(schedule); | |
476 data->set_schedule(schedule); | |
477 } | |
478 }; | |
479 | |
480 | |
481 struct InstructionSelectionPhase { | |
482 static const char* phase_name() { return "select instructions"; } | |
483 | |
484 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { | |
485 InstructionSelector selector(temp_zone, data->graph(), linkage, | |
486 data->sequence(), data->schedule(), | |
487 data->source_positions()); | |
488 selector.SelectInstructions(); | |
489 } | |
490 }; | |
491 | |
492 | |
493 // TODO(dcarney): break this up. | |
494 struct RegisterAllocationPhase { | |
495 static const char* phase_name() { return nullptr; } | |
496 | |
497 void Run(PipelineData* data, Zone* temp_zone) { | |
498 int node_count = data->sequence()->VirtualRegisterCount(); | |
499 if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { | |
500 data->set_compilation_failed(); | |
501 return; | |
502 } | |
503 | |
504 SmartArrayPointer<char> debug_name; | |
505 #ifdef DEBUG | |
506 if (data->info() != nullptr) { | |
507 debug_name = GetDebugName(data->info()); | |
508 } | |
509 #endif | |
510 | |
511 RegisterAllocator allocator(RegisterConfiguration::ArchDefault(), temp_zone, | |
512 data->frame(), data->sequence(), | |
513 debug_name.get()); | |
514 | |
515 if (!allocator.Allocate(data->pipeline_statistics())) { | |
516 data->set_compilation_failed(); | |
517 return; | |
518 } | |
519 | |
520 if (FLAG_trace_turbo) { | |
521 OFStream os(stdout); | |
522 PrintableInstructionSequence printable = { | |
523 RegisterConfiguration::ArchDefault(), data->sequence()}; | |
524 os << "----- Instruction sequence after register allocation -----\n" | |
525 << printable; | |
526 } | |
527 | |
528 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | |
529 TurboCfgFile tcf(data->isolate()); | |
530 tcf << AsC1VAllocator("CodeGen", &allocator); | |
531 } | |
532 } | |
533 }; | |
534 | |
535 | |
536 struct GenerateCodePhase { | |
537 static const char* phase_name() { return "generate code"; } | |
538 | |
539 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage, | |
540 CompilationInfo* info) { | |
541 CodeGenerator generator(data->frame(), linkage, data->sequence(), info); | |
542 data->set_code(generator.GenerateCode()); | |
543 } | |
544 }; | |
545 | |
546 | |
547 struct PrintGraphPhase { | |
548 static const char* phase_name() { return nullptr; } | |
549 | |
550 void Run(PipelineData* data, Zone* temp_zone, const char* phase) { | |
551 CompilationInfo* info = data->info(); | |
552 Graph* graph = data->graph(); | |
188 char buffer[256]; | 553 char buffer[256]; |
189 Vector<char> filename(buffer, sizeof(buffer)); | 554 Vector<char> filename(buffer, sizeof(buffer)); |
190 SmartArrayPointer<char> functionname; | 555 SmartArrayPointer<char> functionname; |
191 if (!info_->shared_info().is_null()) { | 556 if (!info->shared_info().is_null()) { |
192 functionname = info_->shared_info()->DebugName()->ToCString(); | 557 functionname = info->shared_info()->DebugName()->ToCString(); |
193 if (strlen(functionname.get()) > 0) { | 558 if (strlen(functionname.get()) > 0) { |
194 SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase); | 559 SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase); |
195 } else { | 560 } else { |
196 SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info_), phase); | 561 SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info), phase); |
197 } | 562 } |
198 } else { | 563 } else { |
199 SNPrintF(filename, "turbo-none-%s", phase); | 564 SNPrintF(filename, "turbo-none-%s", phase); |
200 } | 565 } |
201 std::replace(filename.start(), filename.start() + filename.length(), ' ', | 566 std::replace(filename.start(), filename.start() + filename.length(), ' ', |
202 '_'); | 567 '_'); |
203 | 568 |
204 char dot_buffer[256]; | 569 char dot_buffer[256]; |
205 Vector<char> dot_filename(dot_buffer, sizeof(dot_buffer)); | 570 Vector<char> dot_filename(dot_buffer, sizeof(dot_buffer)); |
206 SNPrintF(dot_filename, "%s.dot", filename.start()); | 571 SNPrintF(dot_filename, "%s.dot", filename.start()); |
207 FILE* dot_file = base::OS::FOpen(dot_filename.start(), "w+"); | 572 FILE* dot_file = base::OS::FOpen(dot_filename.start(), "w+"); |
208 OFStream dot_of(dot_file); | 573 OFStream dot_of(dot_file); |
209 dot_of << AsDOT(*graph); | 574 dot_of << AsDOT(*graph); |
210 fclose(dot_file); | 575 fclose(dot_file); |
211 | 576 |
212 char json_buffer[256]; | 577 char json_buffer[256]; |
213 Vector<char> json_filename(json_buffer, sizeof(json_buffer)); | 578 Vector<char> json_filename(json_buffer, sizeof(json_buffer)); |
214 SNPrintF(json_filename, "%s.json", filename.start()); | 579 SNPrintF(json_filename, "%s.json", filename.start()); |
215 FILE* json_file = base::OS::FOpen(json_filename.start(), "w+"); | 580 FILE* json_file = base::OS::FOpen(json_filename.start(), "w+"); |
216 OFStream json_of(json_file); | 581 OFStream json_of(json_file); |
217 json_of << AsJSON(*graph); | 582 json_of << AsJSON(*graph); |
218 fclose(json_file); | 583 fclose(json_file); |
219 | 584 |
220 OFStream os(stdout); | 585 OFStream os(stdout); |
221 os << "-- " << phase << " graph printed to file " << filename.start() | 586 os << "-- " << phase << " graph printed to file " << filename.start() |
222 << "\n"; | 587 << "\n"; |
223 } | 588 } |
589 }; | |
590 | |
591 | |
592 struct VerifyGraphPhase { | |
593 static const char* phase_name() { return nullptr; } | |
594 | |
595 void Run(PipelineData* data, Zone* temp_zone, const bool untyped) { | |
596 Verifier::Run(data->graph(), FLAG_turbo_types && !untyped | |
597 ? Verifier::TYPED | |
598 : Verifier::UNTYPED); | |
599 } | |
600 }; | |
601 | |
602 | |
603 void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { | |
604 if (FLAG_trace_turbo) { | |
605 Run<PrintGraphPhase>(phase); | |
606 } | |
224 if (VerifyGraphs()) { | 607 if (VerifyGraphs()) { |
225 Verifier::Run(graph, | 608 Run<VerifyGraphPhase>(untyped); |
226 FLAG_turbo_types && !untyped ? Verifier::TYPED : Verifier::UNTYPED); | |
227 } | 609 } |
228 } | 610 } |
229 | 611 |
230 | 612 |
231 class AstGraphBuilderWithPositions : public AstGraphBuilder { | |
232 public: | |
233 explicit AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info, | |
234 JSGraph* jsgraph, | |
235 SourcePositionTable* source_positions) | |
236 : AstGraphBuilder(local_zone, info, jsgraph), | |
237 source_positions_(source_positions) {} | |
238 | |
239 bool CreateGraph() { | |
240 SourcePositionTable::Scope pos(source_positions_, | |
241 SourcePosition::Unknown()); | |
242 return AstGraphBuilder::CreateGraph(); | |
243 } | |
244 | |
245 #define DEF_VISIT(type) \ | |
246 virtual void Visit##type(type* node) OVERRIDE { \ | |
247 SourcePositionTable::Scope pos(source_positions_, \ | |
248 SourcePosition(node->position())); \ | |
249 AstGraphBuilder::Visit##type(node); \ | |
250 } | |
251 AST_NODE_LIST(DEF_VISIT) | |
252 #undef DEF_VISIT | |
253 | |
254 private: | |
255 SourcePositionTable* source_positions_; | |
256 }; | |
257 | |
258 | |
259 static void TraceSchedule(Schedule* schedule) { | |
260 if (!FLAG_trace_turbo) return; | |
261 OFStream os(stdout); | |
262 os << "-- Schedule --------------------------------------\n" << *schedule; | |
263 } | |
264 | |
265 | |
266 static SmartArrayPointer<char> GetDebugName(CompilationInfo* info) { | |
267 SmartArrayPointer<char> name; | |
268 if (info->IsStub()) { | |
269 if (info->code_stub() != NULL) { | |
270 CodeStub::Major major_key = info->code_stub()->MajorKey(); | |
271 const char* major_name = CodeStub::MajorName(major_key, false); | |
272 size_t len = strlen(major_name); | |
273 name.Reset(new char[len]); | |
274 memcpy(name.get(), major_name, len); | |
275 } | |
276 } else { | |
277 AllowHandleDereference allow_deref; | |
278 name = info->function()->debug_name()->ToCString(); | |
279 } | |
280 return name; | |
281 } | |
282 | |
283 | |
284 Handle<Code> Pipeline::GenerateCode() { | 613 Handle<Code> Pipeline::GenerateCode() { |
285 // This list must be kept in sync with DONT_TURBOFAN_NODE in ast.cc. | 614 // This list must be kept in sync with DONT_TURBOFAN_NODE in ast.cc. |
286 if (info()->function()->dont_optimize_reason() == kTryCatchStatement || | 615 if (info()->function()->dont_optimize_reason() == kTryCatchStatement || |
287 info()->function()->dont_optimize_reason() == kTryFinallyStatement || | 616 info()->function()->dont_optimize_reason() == kTryFinallyStatement || |
288 // TODO(turbofan): Make ES6 for-of work and remove this bailout. | 617 // TODO(turbofan): Make ES6 for-of work and remove this bailout. |
289 info()->function()->dont_optimize_reason() == kForOfStatement || | 618 info()->function()->dont_optimize_reason() == kForOfStatement || |
290 // TODO(turbofan): Make super work and remove this bailout. | 619 // TODO(turbofan): Make super work and remove this bailout. |
291 info()->function()->dont_optimize_reason() == kSuperReference || | 620 info()->function()->dont_optimize_reason() == kSuperReference || |
292 // TODO(turbofan): Make class literals work and remove this bailout. | 621 // TODO(turbofan): Make class literals work and remove this bailout. |
293 info()->function()->dont_optimize_reason() == kClassLiteral || | 622 info()->function()->dont_optimize_reason() == kClassLiteral || |
294 // TODO(turbofan): Make OSR work and remove this bailout. | 623 // TODO(turbofan): Make OSR work and remove this bailout. |
295 info()->is_osr()) { | 624 info()->is_osr()) { |
296 return Handle<Code>::null(); | 625 return Handle<Code>::null(); |
297 } | 626 } |
298 | 627 |
299 ZonePool zone_pool(isolate()); | 628 ZonePool zone_pool(isolate()); |
629 SmartPointer<PipelineStatistics> pipeline_statistics; | |
300 | 630 |
301 SmartPointer<PipelineStatistics> pipeline_statistics; | |
302 if (FLAG_turbo_stats) { | 631 if (FLAG_turbo_stats) { |
303 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); | 632 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); |
304 pipeline_statistics->BeginPhaseKind("graph creation"); | 633 pipeline_statistics->BeginPhaseKind("graph creation"); |
305 } | 634 } |
306 | 635 |
636 PipelineData data(info(), &zone_pool, pipeline_statistics.get()); | |
637 this->data_ = &data; | |
638 | |
307 if (FLAG_trace_turbo) { | 639 if (FLAG_trace_turbo) { |
308 OFStream os(stdout); | 640 OFStream os(stdout); |
309 os << "---------------------------------------------------\n" | 641 os << "---------------------------------------------------\n" |
310 << "Begin compiling method " << GetDebugName(info()).get() | 642 << "Begin compiling method " << GetDebugName(info()).get() |
311 << " using Turbofan" << std::endl; | 643 << " using Turbofan" << std::endl; |
312 TurboCfgFile tcf(isolate()); | 644 TurboCfgFile tcf(isolate()); |
313 tcf << AsC1VCompilation(info()); | 645 tcf << AsC1VCompilation(info()); |
314 } | 646 } |
315 | 647 |
316 // Initialize the graph and builders. | |
317 PipelineData data(info(), &zone_pool, pipeline_statistics.get()); | |
318 | |
319 data.source_positions()->AddDecorator(); | 648 data.source_positions()->AddDecorator(); |
320 | 649 |
321 Node* context_node; | 650 Run<GraphBuilderPhase>(); |
322 { | 651 if (data.compilation_failed()) return Handle<Code>::null(); |
323 PhaseScope phase_scope(pipeline_statistics.get(), "graph builder"); | 652 RunPrintAndVerify("Initial untyped", true); |
324 ZonePool::Scope zone_scope(data.zone_pool()); | |
325 AstGraphBuilderWithPositions graph_builder( | |
326 zone_scope.zone(), info(), data.jsgraph(), data.source_positions()); | |
327 if (!graph_builder.CreateGraph()) return Handle<Code>::null(); | |
328 context_node = graph_builder.GetFunctionContext(); | |
329 } | |
330 | 653 |
331 VerifyAndPrintGraph(data.graph(), "Initial untyped", true); | 654 Run<EarlyControlReductionPhase>(); |
332 | 655 RunPrintAndVerify("Early Control reduced", true); |
333 { | |
334 PhaseScope phase_scope(pipeline_statistics.get(), | |
335 "early control reduction"); | |
336 SourcePositionTable::Scope pos(data.source_positions(), | |
337 SourcePosition::Unknown()); | |
338 ZonePool::Scope zone_scope(data.zone_pool()); | |
339 ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(), | |
340 data.common()); | |
341 | |
342 VerifyAndPrintGraph(data.graph(), "Early Control reduced", true); | |
343 } | |
344 | 656 |
345 if (info()->is_context_specializing()) { | 657 if (info()->is_context_specializing()) { |
346 SourcePositionTable::Scope pos(data.source_positions(), | |
347 SourcePosition::Unknown()); | |
348 // Specialize the code to the context as aggressively as possible. | 658 // Specialize the code to the context as aggressively as possible. |
349 JSContextSpecializer spec(info(), data.jsgraph(), context_node); | 659 Run<ContextSpecializerPhase>(); |
350 spec.SpecializeToContext(); | 660 RunPrintAndVerify("Context specialized", true); |
351 VerifyAndPrintGraph(data.graph(), "Context specialized", true); | |
352 } | 661 } |
353 | 662 |
354 if (info()->is_inlining_enabled()) { | 663 if (info()->is_inlining_enabled()) { |
355 PhaseScope phase_scope(pipeline_statistics.get(), "inlining"); | 664 Run<InliningPhase>(); |
356 SourcePositionTable::Scope pos(data.source_positions(), | 665 RunPrintAndVerify("Inlined", true); |
357 SourcePosition::Unknown()); | |
358 ZonePool::Scope zone_scope(data.zone_pool()); | |
359 JSInliner inliner(zone_scope.zone(), info(), data.jsgraph()); | |
360 inliner.Inline(); | |
361 VerifyAndPrintGraph(data.graph(), "Inlined", true); | |
362 } | 666 } |
363 | 667 |
364 // Print a replay of the initial graph. | |
365 if (FLAG_print_turbo_replay) { | 668 if (FLAG_print_turbo_replay) { |
669 // Print a replay of the initial graph. | |
366 GraphReplayPrinter::PrintReplay(data.graph()); | 670 GraphReplayPrinter::PrintReplay(data.graph()); |
367 } | 671 } |
368 | 672 |
369 // Bailout here in case target architecture is not supported. | 673 // Bailout here in case target architecture is not supported. |
370 if (!SupportedTarget()) return Handle<Code>::null(); | 674 if (!SupportedTarget()) return Handle<Code>::null(); |
371 | 675 |
372 if (info()->is_typing_enabled()) { | 676 if (info()->is_typing_enabled()) { |
373 { | 677 // Type the graph. |
374 // Type the graph. | 678 Run<TyperPhase>(); |
375 PhaseScope phase_scope(pipeline_statistics.get(), "typer"); | 679 RunPrintAndVerify("Typed"); |
376 data.typer()->Run(); | |
377 VerifyAndPrintGraph(data.graph(), "Typed"); | |
378 } | |
379 } | 680 } |
380 | 681 |
381 if (!pipeline_statistics.is_empty()) { | 682 if (!pipeline_statistics.is_empty()) { |
382 pipeline_statistics->BeginPhaseKind("lowering"); | 683 data.pipeline_statistics()->BeginPhaseKind("lowering"); |
383 } | 684 } |
384 | 685 |
385 if (info()->is_typing_enabled()) { | 686 if (info()->is_typing_enabled()) { |
386 { | 687 // Lower JSOperators where we can determine types. |
387 // Lower JSOperators where we can determine types. | 688 Run<TypedLoweringPhase>(); |
388 PhaseScope phase_scope(pipeline_statistics.get(), "typed lowering"); | 689 RunPrintAndVerify("Lowered typed"); |
389 SourcePositionTable::Scope pos(data.source_positions(), | |
390 SourcePosition::Unknown()); | |
391 ValueNumberingReducer vn_reducer(data.graph_zone()); | |
392 JSTypedLowering lowering(data.jsgraph()); | |
393 SimplifiedOperatorReducer simple_reducer(data.jsgraph()); | |
394 GraphReducer graph_reducer(data.graph()); | |
395 graph_reducer.AddReducer(&vn_reducer); | |
396 graph_reducer.AddReducer(&lowering); | |
397 graph_reducer.AddReducer(&simple_reducer); | |
398 graph_reducer.ReduceGraph(); | |
399 | 690 |
400 VerifyAndPrintGraph(data.graph(), "Lowered typed"); | 691 // Lower simplified operators and insert changes. |
401 } | 692 Run<SimplifiedLoweringPhase>(); |
402 { | 693 RunPrintAndVerify("Lowered simplified"); |
403 // Lower simplified operators and insert changes. | |
404 PhaseScope phase_scope(pipeline_statistics.get(), "simplified lowering"); | |
405 SourcePositionTable::Scope pos(data.source_positions(), | |
406 SourcePosition::Unknown()); | |
407 SimplifiedLowering lowering(data.jsgraph()); | |
408 lowering.LowerAllNodes(); | |
409 ValueNumberingReducer vn_reducer(data.graph_zone()); | |
410 SimplifiedOperatorReducer simple_reducer(data.jsgraph()); | |
411 GraphReducer graph_reducer(data.graph()); | |
412 graph_reducer.AddReducer(&vn_reducer); | |
413 graph_reducer.AddReducer(&simple_reducer); | |
414 graph_reducer.ReduceGraph(); | |
415 | 694 |
416 VerifyAndPrintGraph(data.graph(), "Lowered simplified"); | 695 // Lower changes that have been inserted before. |
417 } | 696 Run<ChangeLoweringPhase>(); |
418 { | 697 // // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
419 // Lower changes that have been inserted before. | 698 RunPrintAndVerify("Lowered changes", true); |
420 PhaseScope phase_scope(pipeline_statistics.get(), "change lowering"); | |
421 SourcePositionTable::Scope pos(data.source_positions(), | |
422 SourcePosition::Unknown()); | |
423 Linkage linkage(data.graph_zone(), info()); | |
424 ValueNumberingReducer vn_reducer(data.graph_zone()); | |
425 SimplifiedOperatorReducer simple_reducer(data.jsgraph()); | |
426 ChangeLowering lowering(data.jsgraph(), &linkage); | |
427 MachineOperatorReducer mach_reducer(data.jsgraph()); | |
428 GraphReducer graph_reducer(data.graph()); | |
429 // TODO(titzer): Figure out if we should run all reducers at once here. | |
430 graph_reducer.AddReducer(&vn_reducer); | |
431 graph_reducer.AddReducer(&simple_reducer); | |
432 graph_reducer.AddReducer(&lowering); | |
433 graph_reducer.AddReducer(&mach_reducer); | |
434 graph_reducer.ReduceGraph(); | |
435 | 699 |
436 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 700 Run<LateControlReductionPhase>(); |
437 VerifyAndPrintGraph(data.graph(), "Lowered changes", true); | 701 RunPrintAndVerify("Late Control reduced"); |
438 } | |
439 | |
440 { | |
441 PhaseScope phase_scope(pipeline_statistics.get(), | |
442 "late control reduction"); | |
443 SourcePositionTable::Scope pos(data.source_positions(), | |
444 SourcePosition::Unknown()); | |
445 ZonePool::Scope zone_scope(data.zone_pool()); | |
446 ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(), | |
447 data.common()); | |
448 | |
449 VerifyAndPrintGraph(data.graph(), "Late Control reduced"); | |
450 } | |
451 } | 702 } |
452 | 703 |
453 { | 704 // Lower any remaining generic JSOperators. |
454 // Lower any remaining generic JSOperators. | 705 Run<GenericLoweringPhase>(); |
455 PhaseScope phase_scope(pipeline_statistics.get(), "generic lowering"); | 706 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
456 SourcePositionTable::Scope pos(data.source_positions(), | 707 RunPrintAndVerify("Lowered generic", true); |
457 SourcePosition::Unknown()); | |
458 JSGenericLowering generic(info(), data.jsgraph()); | |
459 SelectLowering select(data.jsgraph()->graph(), data.jsgraph()->common()); | |
460 GraphReducer graph_reducer(data.graph()); | |
461 graph_reducer.AddReducer(&generic); | |
462 graph_reducer.AddReducer(&select); | |
463 graph_reducer.ReduceGraph(); | |
464 | |
465 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | |
466 VerifyAndPrintGraph(data.graph(), "Lowered generic", true); | |
467 } | |
468 | 708 |
469 if (!pipeline_statistics.is_empty()) { | 709 if (!pipeline_statistics.is_empty()) { |
470 pipeline_statistics->BeginPhaseKind("block building"); | 710 data.pipeline_statistics()->BeginPhaseKind("block building"); |
471 } | 711 } |
472 | 712 |
473 data.source_positions()->RemoveDecorator(); | 713 data.source_positions()->RemoveDecorator(); |
474 | 714 |
475 // Compute a schedule. | 715 // Compute a schedule. |
476 ComputeSchedule(&data); | 716 Run<ComputeSchedulePhase>(); |
477 | 717 |
478 Handle<Code> code = Handle<Code>::null(); | |
479 { | 718 { |
480 // Generate optimized code. | 719 // Generate optimized code. |
481 Linkage linkage(data.instruction_zone(), info()); | 720 Linkage linkage(data.instruction_zone(), info()); |
482 code = GenerateCode(&linkage, &data); | 721 GenerateCode(&linkage); |
483 info()->SetCode(code); | |
484 } | 722 } |
723 Handle<Code> code = data.code(); | |
724 info()->SetCode(code); | |
485 | 725 |
486 // Print optimized code. | 726 // Print optimized code. |
487 v8::internal::CodeGenerator::PrintCode(code, info()); | 727 v8::internal::CodeGenerator::PrintCode(code, info()); |
488 | 728 |
489 if (FLAG_trace_turbo) { | 729 if (FLAG_trace_turbo) { |
490 OFStream os(stdout); | 730 OFStream os(stdout); |
491 os << "--------------------------------------------------\n" | 731 os << "--------------------------------------------------\n" |
492 << "Finished compiling method " << GetDebugName(info()).get() | 732 << "Finished compiling method " << GetDebugName(info()).get() |
493 << " using Turbofan" << std::endl; | 733 << " using Turbofan" << std::endl; |
494 } | 734 } |
495 | 735 |
496 return code; | 736 return code; |
497 } | 737 } |
498 | 738 |
499 | 739 |
500 void Pipeline::ComputeSchedule(PipelineData* data) { | |
501 PhaseScope phase_scope(data->pipeline_statistics(), "scheduling"); | |
502 ZonePool::Scope zone_scope(data->zone_pool()); | |
503 Schedule* schedule = | |
504 Scheduler::ComputeSchedule(zone_scope.zone(), data->graph()); | |
505 TraceSchedule(schedule); | |
506 if (VerifyGraphs()) ScheduleVerifier::Run(schedule); | |
507 data->set_schedule(schedule); | |
508 } | |
509 | |
510 | |
511 Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, | 740 Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
512 Graph* graph, | 741 Graph* graph, |
513 Schedule* schedule) { | 742 Schedule* schedule) { |
514 ZonePool zone_pool(isolate()); | 743 ZonePool zone_pool(isolate()); |
515 CHECK(SupportedBackend()); | 744 CHECK(SupportedBackend()); |
516 PipelineData data(graph, schedule, &zone_pool); | 745 PipelineData data(graph, schedule, &zone_pool); |
746 this->data_ = &data; | |
517 if (schedule == NULL) { | 747 if (schedule == NULL) { |
518 // TODO(rossberg): Should this really be untyped? | 748 // TODO(rossberg): Should this really be untyped? |
519 VerifyAndPrintGraph(graph, "Machine", true); | 749 RunPrintAndVerify("Machine", true); |
520 ComputeSchedule(&data); | 750 Run<ComputeSchedulePhase>(); |
521 } else { | 751 } else { |
522 TraceSchedule(schedule); | 752 TraceSchedule(schedule); |
523 } | 753 } |
524 | 754 |
525 Handle<Code> code = GenerateCode(linkage, &data); | 755 GenerateCode(linkage); |
756 Handle<Code> code = data.code(); | |
757 | |
526 #if ENABLE_DISASSEMBLER | 758 #if ENABLE_DISASSEMBLER |
527 if (!code.is_null() && FLAG_print_opt_code) { | 759 if (!code.is_null() && FLAG_print_opt_code) { |
528 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); | 760 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); |
529 OFStream os(tracing_scope.file()); | 761 OFStream os(tracing_scope.file()); |
530 code->Disassemble("test code", os); | 762 code->Disassemble("test code", os); |
531 } | 763 } |
532 #endif | 764 #endif |
533 return code; | 765 return code; |
534 } | 766 } |
535 | 767 |
536 | 768 |
537 Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) { | 769 void Pipeline::GenerateCode(Linkage* linkage) { |
770 PipelineData* data = this->data_; | |
771 | |
538 DCHECK_NOT_NULL(linkage); | 772 DCHECK_NOT_NULL(linkage); |
539 DCHECK_NOT_NULL(data->graph()); | 773 DCHECK_NOT_NULL(data->graph()); |
540 DCHECK_NOT_NULL(data->schedule()); | 774 DCHECK_NOT_NULL(data->schedule()); |
541 CHECK(SupportedBackend()); | 775 CHECK(SupportedBackend()); |
542 | 776 |
543 BasicBlockProfiler::Data* profiler_data = NULL; | 777 BasicBlockProfiler::Data* profiler_data = NULL; |
544 if (FLAG_turbo_profiling) { | 778 if (FLAG_turbo_profiling) { |
545 profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(), | 779 profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(), |
546 data->schedule()); | 780 data->schedule()); |
547 } | 781 } |
548 | 782 |
549 InstructionBlocks* instruction_blocks = | 783 InstructionBlocks* instruction_blocks = |
550 InstructionSequence::InstructionBlocksFor(data->instruction_zone(), | 784 InstructionSequence::InstructionBlocksFor(data->instruction_zone(), |
551 data->schedule()); | 785 data->schedule()); |
552 InstructionSequence sequence(data->instruction_zone(), instruction_blocks); | 786 data->set_sequence(new (data->instruction_zone()) InstructionSequence( |
787 data->instruction_zone(), instruction_blocks)); | |
553 | 788 |
554 // Select and schedule instructions covering the scheduled graph. | 789 // Select and schedule instructions covering the scheduled graph. |
555 { | 790 Run<InstructionSelectionPhase>(linkage); |
556 PhaseScope phase_scope(data->pipeline_statistics(), "select instructions"); | |
557 ZonePool::Scope zone_scope(data->zone_pool()); | |
558 InstructionSelector selector(zone_scope.zone(), data->graph(), linkage, | |
559 &sequence, data->schedule(), | |
560 data->source_positions()); | |
561 selector.SelectInstructions(); | |
562 } | |
563 | 791 |
564 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | 792 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
565 TurboCfgFile tcf(isolate()); | 793 TurboCfgFile tcf(isolate()); |
566 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), | 794 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), |
567 &sequence); | 795 data->sequence()); |
568 } | 796 } |
569 | 797 |
570 data->DeleteGraphZone(); | 798 data->DeleteGraphZone(); |
571 | 799 |
572 if (data->pipeline_statistics() != NULL) { | 800 if (data->pipeline_statistics() != NULL) { |
573 data->pipeline_statistics()->BeginPhaseKind("register allocation"); | 801 data->pipeline_statistics()->BeginPhaseKind("register allocation"); |
574 } | 802 } |
575 | 803 |
576 #ifdef DEBUG | 804 #ifdef DEBUG |
577 // Don't track usage for this zone in compiler stats. | 805 // Don't track usage for this zone in compiler stats. |
578 Zone verifier_zone(info()->isolate()); | 806 Zone verifier_zone(info()->isolate()); |
579 RegisterAllocatorVerifier verifier( | 807 RegisterAllocatorVerifier verifier( |
580 &verifier_zone, RegisterConfiguration::ArchDefault(), &sequence); | 808 &verifier_zone, RegisterConfiguration::ArchDefault(), data->sequence()); |
581 #endif | 809 #endif |
582 | 810 |
583 // Allocate registers. | 811 // Allocate registers. |
584 Frame frame; | 812 data->set_frame(new (data->instruction_zone()) Frame); |
585 { | 813 Run<RegisterAllocationPhase>(); |
586 int node_count = sequence.VirtualRegisterCount(); | 814 if (data->compilation_failed()) { |
587 if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { | 815 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
588 info()->AbortOptimization(kNotEnoughVirtualRegistersForValues); | 816 return; |
589 return Handle<Code>::null(); | |
590 } | |
591 ZonePool::Scope zone_scope(data->zone_pool()); | |
592 | |
593 SmartArrayPointer<char> debug_name; | |
594 #ifdef DEBUG | |
595 debug_name = GetDebugName(info()); | |
596 #endif | |
597 | |
598 RegisterAllocator allocator(RegisterConfiguration::ArchDefault(), | |
599 zone_scope.zone(), &frame, &sequence, | |
600 debug_name.get()); | |
601 if (!allocator.Allocate(data->pipeline_statistics())) { | |
602 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); | |
603 return Handle<Code>::null(); | |
604 } | |
605 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | |
606 TurboCfgFile tcf(isolate()); | |
607 tcf << AsC1VAllocator("CodeGen", &allocator); | |
608 } | |
609 } | |
610 | |
611 if (FLAG_trace_turbo) { | |
612 OFStream os(stdout); | |
613 PrintableInstructionSequence printable = { | |
614 RegisterConfiguration::ArchDefault(), &sequence}; | |
615 os << "----- Instruction sequence after register allocation -----\n" | |
616 << printable; | |
617 } | 817 } |
618 | 818 |
619 #ifdef DEBUG | 819 #ifdef DEBUG |
620 verifier.VerifyAssignment(); | 820 verifier.VerifyAssignment(); |
621 verifier.VerifyGapMoves(); | 821 verifier.VerifyGapMoves(); |
622 #endif | 822 #endif |
623 | 823 |
624 if (data->pipeline_statistics() != NULL) { | 824 if (data->pipeline_statistics() != NULL) { |
625 data->pipeline_statistics()->BeginPhaseKind("code generation"); | 825 data->pipeline_statistics()->BeginPhaseKind("code generation"); |
626 } | 826 } |
627 | 827 |
628 // Generate native sequence. | 828 // Generate native sequence. |
629 Handle<Code> code; | 829 Run<GenerateCodePhase>(linkage, info()); |
630 { | 830 |
631 PhaseScope phase_scope(data->pipeline_statistics(), "generate code"); | |
632 CodeGenerator generator(&frame, linkage, &sequence, info()); | |
633 code = generator.GenerateCode(); | |
634 } | |
635 if (profiler_data != NULL) { | 831 if (profiler_data != NULL) { |
636 #if ENABLE_DISASSEMBLER | 832 #if ENABLE_DISASSEMBLER |
637 std::ostringstream os; | 833 std::ostringstream os; |
638 code->Disassemble(NULL, os); | 834 data->code()->Disassemble(NULL, os); |
639 profiler_data->SetCode(&os); | 835 profiler_data->SetCode(&os); |
640 #endif | 836 #endif |
641 } | 837 } |
642 return code; | |
643 } | 838 } |
644 | 839 |
645 | 840 |
646 void Pipeline::SetUp() { | 841 void Pipeline::SetUp() { |
647 InstructionOperand::SetUpCaches(); | 842 InstructionOperand::SetUpCaches(); |
648 } | 843 } |
649 | 844 |
650 | 845 |
651 void Pipeline::TearDown() { | 846 void Pipeline::TearDown() { |
652 InstructionOperand::TearDownCaches(); | 847 InstructionOperand::TearDownCaches(); |
653 } | 848 } |
654 | 849 |
655 } // namespace compiler | 850 } // namespace compiler |
656 } // namespace internal | 851 } // namespace internal |
657 } // namespace v8 | 852 } // namespace v8 |
OLD | NEW |