| 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 |