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"; } |
| 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 |