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...) 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), | |
52 graph_zone_scope_(zone_pool_), | 54 graph_zone_scope_(zone_pool_), |
53 graph_zone_(graph_zone_scope_.zone()), | 55 graph_zone_(graph_zone_scope_.zone()), |
54 graph_(new (graph_zone()) Graph(graph_zone())), | 56 graph_(new (graph_zone()) Graph(graph_zone())), |
55 source_positions_(new SourcePositionTable(graph())), | 57 source_positions_(new SourcePositionTable(graph())), |
56 machine_(new (graph_zone()) MachineOperatorBuilder( | 58 machine_(new (graph_zone()) MachineOperatorBuilder( |
57 graph_zone(), kMachPtr, | 59 graph_zone(), kMachPtr, |
58 InstructionSelector::SupportedMachineOperatorFlags())), | 60 InstructionSelector::SupportedMachineOperatorFlags())), |
59 common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())), | 61 common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())), |
60 javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())), | 62 javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())), |
61 jsgraph_(new (graph_zone()) | 63 jsgraph_(new (graph_zone()) |
62 JSGraph(graph(), common(), javascript(), machine())), | 64 JSGraph(graph(), common(), javascript(), machine())), |
63 typer_(new Typer(graph(), info->context())), | 65 typer_(new Typer(graph(), info->context())), |
64 schedule_(NULL), | 66 context_node_(nullptr), |
67 schedule_(nullptr), | |
65 instruction_zone_scope_(zone_pool_), | 68 instruction_zone_scope_(zone_pool_), |
66 instruction_zone_(instruction_zone_scope_.zone()) {} | 69 instruction_zone_(instruction_zone_scope_.zone()) {} |
67 | 70 |
71 | |
68 // For machine graph testing only. | 72 // For machine graph testing only. |
69 PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool) | 73 PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool) |
70 : isolate_(graph->zone()->isolate()), | 74 : isolate_(graph->zone()->isolate()), |
71 outer_zone_(NULL), | 75 info_(nullptr), |
76 outer_zone_(nullptr), | |
72 zone_pool_(zone_pool), | 77 zone_pool_(zone_pool), |
73 pipeline_statistics_(NULL), | 78 pipeline_statistics_(nullptr), |
79 compilation_failed_(false), | |
74 graph_zone_scope_(zone_pool_), | 80 graph_zone_scope_(zone_pool_), |
75 graph_zone_(NULL), | 81 graph_zone_(nullptr), |
76 graph_(graph), | 82 graph_(graph), |
77 source_positions_(new SourcePositionTable(graph)), | 83 source_positions_(new SourcePositionTable(graph)), |
78 machine_(NULL), | 84 machine_(nullptr), |
79 common_(NULL), | 85 common_(nullptr), |
80 javascript_(NULL), | 86 javascript_(nullptr), |
81 jsgraph_(NULL), | 87 jsgraph_(nullptr), |
82 typer_(NULL), | 88 typer_(nullptr), |
89 context_node_(nullptr), | |
83 schedule_(schedule), | 90 schedule_(schedule), |
84 instruction_zone_scope_(zone_pool_), | 91 instruction_zone_scope_(zone_pool_), |
85 instruction_zone_(instruction_zone_scope_.zone()) {} | 92 instruction_zone_(instruction_zone_scope_.zone()) {} |
86 | 93 |
87 ~PipelineData() { | 94 ~PipelineData() { |
88 DeleteInstructionZone(); | 95 DeleteInstructionZone(); |
89 DeleteGraphZone(); | 96 DeleteGraphZone(); |
90 } | 97 } |
91 | 98 |
92 Isolate* isolate() const { return isolate_; } | 99 Isolate* isolate() const { return isolate_; } |
100 CompilationInfo* info() const { return info_; } | |
93 ZonePool* zone_pool() const { return zone_pool_; } | 101 ZonePool* zone_pool() const { return zone_pool_; } |
94 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } | 102 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } |
103 bool compilation_failed() const { return compilation_failed_; } | |
104 void set_compilation_failed() { compilation_failed_ = true; } | |
95 | 105 |
96 Zone* graph_zone() const { return graph_zone_; } | 106 Zone* graph_zone() const { return graph_zone_; } |
97 Graph* graph() const { return graph_; } | 107 Graph* graph() const { return graph_; } |
98 SourcePositionTable* source_positions() const { | 108 SourcePositionTable* source_positions() const { |
99 return source_positions_.get(); | 109 return source_positions_.get(); |
100 } | 110 } |
101 MachineOperatorBuilder* machine() const { return machine_; } | 111 MachineOperatorBuilder* machine() const { return machine_; } |
102 CommonOperatorBuilder* common() const { return common_; } | 112 CommonOperatorBuilder* common() const { return common_; } |
103 JSOperatorBuilder* javascript() const { return javascript_; } | 113 JSOperatorBuilder* javascript() const { return javascript_; } |
104 JSGraph* jsgraph() const { return jsgraph_; } | 114 JSGraph* jsgraph() const { return jsgraph_; } |
105 Typer* typer() const { return typer_.get(); } | 115 Typer* typer() const { return typer_.get(); } |
116 Node* context_node() const { return context_node_; } | |
117 void set_context_node(Node* context_node) { context_node_ = context_node; } | |
118 | |
106 Schedule* schedule() const { return schedule_; } | 119 Schedule* schedule() const { return schedule_; } |
107 void set_schedule(Schedule* schedule) { | 120 void set_schedule(Schedule* schedule) { |
108 DCHECK_EQ(NULL, schedule_); | 121 DCHECK_EQ(nullptr, schedule_); |
109 schedule_ = schedule; | 122 schedule_ = schedule; |
110 } | 123 } |
111 | 124 |
112 Zone* instruction_zone() const { return instruction_zone_; } | 125 Zone* instruction_zone() const { return instruction_zone_; } |
113 // RawMachineAssembler generally produces graphs which cannot be verified. | 126 // RawMachineAssembler generally produces graphs which cannot be verified. |
114 bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } | 127 bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } |
115 | 128 |
116 void DeleteGraphZone() { | 129 void DeleteGraphZone() { |
117 // Destroy objects with destructors first. | 130 // Destroy objects with destructors first. |
118 source_positions_.Reset(NULL); | 131 source_positions_.Reset(nullptr); |
119 typer_.Reset(NULL); | 132 typer_.Reset(nullptr); |
120 if (graph_zone_ == NULL) return; | 133 if (graph_zone_ == nullptr) return; |
121 // Destroy zone and clear pointers. | 134 // Destroy zone and clear pointers. |
122 graph_zone_scope_.Destroy(); | 135 graph_zone_scope_.Destroy(); |
123 graph_zone_ = NULL; | 136 graph_zone_ = nullptr; |
124 graph_ = NULL; | 137 graph_ = nullptr; |
125 machine_ = NULL; | 138 machine_ = nullptr; |
126 common_ = NULL; | 139 common_ = nullptr; |
127 javascript_ = NULL; | 140 javascript_ = nullptr; |
128 jsgraph_ = NULL; | 141 jsgraph_ = nullptr; |
129 schedule_ = NULL; | 142 context_node_ = nullptr; |
143 schedule_ = nullptr; | |
130 } | 144 } |
131 | 145 |
132 void DeleteInstructionZone() { | 146 void DeleteInstructionZone() { |
133 if (instruction_zone_ == NULL) return; | 147 if (instruction_zone_ == NULL) return; |
134 instruction_zone_scope_.Destroy(); | 148 instruction_zone_scope_.Destroy(); |
135 instruction_zone_ = NULL; | 149 instruction_zone_ = NULL; |
136 } | 150 } |
137 | 151 |
138 private: | 152 private: |
139 Isolate* isolate_; | 153 Isolate* isolate_; |
154 CompilationInfo* info_; | |
140 Zone* outer_zone_; | 155 Zone* outer_zone_; |
141 ZonePool* zone_pool_; | 156 ZonePool* zone_pool_; |
142 PipelineStatistics* pipeline_statistics_; | 157 PipelineStatistics* pipeline_statistics_; |
158 bool compilation_failed_; | |
143 | 159 |
144 ZonePool::Scope graph_zone_scope_; | 160 ZonePool::Scope graph_zone_scope_; |
145 Zone* graph_zone_; | 161 Zone* graph_zone_; |
146 // All objects in the following group of fields are allocated in graph_zone_. | 162 // 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. | 163 // They are all set to NULL when the graph_zone_ is destroyed. |
148 Graph* graph_; | 164 Graph* graph_; |
149 // TODO(dcarney): make this into a ZoneObject. | 165 // TODO(dcarney): make this into a ZoneObject. |
150 SmartPointer<SourcePositionTable> source_positions_; | 166 SmartPointer<SourcePositionTable> source_positions_; |
151 MachineOperatorBuilder* machine_; | 167 MachineOperatorBuilder* machine_; |
152 CommonOperatorBuilder* common_; | 168 CommonOperatorBuilder* common_; |
153 JSOperatorBuilder* javascript_; | 169 JSOperatorBuilder* javascript_; |
154 JSGraph* jsgraph_; | 170 JSGraph* jsgraph_; |
155 // TODO(dcarney): make this into a ZoneObject. | 171 // TODO(dcarney): make this into a ZoneObject. |
156 SmartPointer<Typer> typer_; | 172 SmartPointer<Typer> typer_; |
173 Node* context_node_; | |
157 Schedule* schedule_; | 174 Schedule* schedule_; |
158 | 175 |
159 // All objects in the following group of fields are allocated in | 176 // 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 | 177 // instruction_zone_. They are all set to NULL when the instruction_zone_ is |
161 // destroyed. | 178 // destroyed. |
162 ZonePool::Scope instruction_zone_scope_; | 179 ZonePool::Scope instruction_zone_scope_; |
163 Zone* instruction_zone_; | 180 Zone* instruction_zone_; |
164 | 181 |
165 DISALLOW_COPY_AND_ASSIGN(PipelineData); | 182 DISALLOW_COPY_AND_ASSIGN(PipelineData); |
166 }; | 183 }; |
167 | 184 |
168 | 185 |
169 static inline bool VerifyGraphs() { | 186 static inline bool VerifyGraphs() { |
170 #ifdef DEBUG | 187 #ifdef DEBUG |
171 return true; | 188 return true; |
172 #else | 189 #else |
173 return FLAG_turbo_verify; | 190 return FLAG_turbo_verify; |
174 #endif | 191 #endif |
175 } | 192 } |
176 | 193 |
177 | 194 |
178 struct TurboCfgFile : public std::ofstream { | 195 struct TurboCfgFile : public std::ofstream { |
179 explicit TurboCfgFile(Isolate* isolate) | 196 explicit TurboCfgFile(Isolate* isolate) |
180 : std::ofstream(isolate->GetTurboCfgFileName().c_str(), | 197 : std::ofstream(isolate->GetTurboCfgFileName().c_str(), |
181 std::ios_base::app) {} | 198 std::ios_base::app) {} |
182 }; | 199 }; |
183 | 200 |
184 | 201 |
185 void Pipeline::VerifyAndPrintGraph( | 202 static void TraceSchedule(Schedule* schedule) { |
186 Graph* graph, const char* phase, bool untyped) { | 203 if (!FLAG_trace_turbo) return; |
187 if (FLAG_trace_turbo) { | 204 OFStream os(stdout); |
205 os << "-- Schedule --------------------------------------\n" << *schedule; | |
206 } | |
207 | |
208 | |
209 static SmartArrayPointer<char> GetDebugName(CompilationInfo* info) { | |
210 SmartArrayPointer<char> name; | |
211 if (info->IsStub()) { | |
212 if (info->code_stub() != NULL) { | |
213 CodeStub::Major major_key = info->code_stub()->MajorKey(); | |
214 const char* major_name = CodeStub::MajorName(major_key, false); | |
215 size_t len = strlen(major_name); | |
216 name.Reset(new char[len]); | |
217 memcpy(name.get(), major_name, len); | |
218 } | |
219 } else { | |
220 AllowHandleDereference allow_deref; | |
221 name = info->function()->debug_name()->ToCString(); | |
222 } | |
223 return name; | |
224 } | |
225 | |
226 | |
227 class AstGraphBuilderWithPositions : public AstGraphBuilder { | |
228 public: | |
229 explicit AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info, | |
230 JSGraph* jsgraph, | |
231 SourcePositionTable* source_positions) | |
232 : AstGraphBuilder(local_zone, info, jsgraph), | |
233 source_positions_(source_positions) {} | |
234 | |
235 bool CreateGraph() { | |
236 SourcePositionTable::Scope pos(source_positions_, | |
237 SourcePosition::Unknown()); | |
238 return AstGraphBuilder::CreateGraph(); | |
239 } | |
240 | |
241 #define DEF_VISIT(type) \ | |
242 virtual void Visit##type(type* node) OVERRIDE { \ | |
243 SourcePositionTable::Scope pos(source_positions_, \ | |
244 SourcePosition(node->position())); \ | |
245 AstGraphBuilder::Visit##type(node); \ | |
246 } | |
247 AST_NODE_LIST(DEF_VISIT) | |
248 #undef DEF_VISIT | |
249 | |
250 Node* GetFunctionContext() { return AstGraphBuilder::GetFunctionContext(); } | |
251 | |
252 private: | |
253 SourcePositionTable* source_positions_; | |
254 }; | |
255 | |
256 | |
257 struct GraphBuilderPhase { | |
258 void Run(PipelineData* data) { | |
titzer
2014/11/14 14:03:40
I like this a lot better!
Can we pull the phase_s
| |
259 PhaseScope phase_scope(data->pipeline_statistics(), "graph builder"); | |
260 ZonePool::Scope zone_scope(data->zone_pool()); | |
261 AstGraphBuilderWithPositions graph_builder(zone_scope.zone(), data->info(), | |
262 data->jsgraph(), | |
263 data->source_positions()); | |
264 if (!graph_builder.CreateGraph()) { | |
265 data->set_compilation_failed(); | |
266 return; | |
267 } | |
268 data->set_context_node(graph_builder.GetFunctionContext()); | |
269 } | |
270 }; | |
271 | |
272 | |
273 struct ContextSpecializerPhase { | |
274 void Run(PipelineData* data) { | |
275 SourcePositionTable::Scope pos(data->source_positions(), | |
276 SourcePosition::Unknown()); | |
277 JSContextSpecializer spec(data->info(), data->jsgraph(), | |
278 data->context_node()); | |
279 spec.SpecializeToContext(); | |
280 } | |
281 }; | |
282 | |
283 | |
284 struct InliningPhase { | |
285 void Run(PipelineData* data) { | |
286 PhaseScope phase_scope(data->pipeline_statistics(), "inlining"); | |
287 ZonePool::Scope zone_scope(data->zone_pool()); | |
288 SourcePositionTable::Scope pos(data->source_positions(), | |
289 SourcePosition::Unknown()); | |
290 JSInliner inliner(zone_scope.zone(), data->info(), data->jsgraph()); | |
291 inliner.Inline(); | |
292 } | |
293 }; | |
294 | |
295 | |
296 struct TyperPhase { | |
297 void Run(PipelineData* data) { | |
298 PhaseScope phase_scope(data->pipeline_statistics(), "typer"); | |
299 ZonePool::Scope zone_scope(data->zone_pool()); | |
300 data->typer()->Run(); | |
301 } | |
302 }; | |
303 | |
304 | |
305 struct TypedLoweringPhase { | |
306 void Run(PipelineData* data) { | |
307 PhaseScope phase_scope(data->pipeline_statistics(), "typed lowering"); | |
308 ZonePool::Scope zone_scope(data->zone_pool()); | |
309 SourcePositionTable::Scope pos(data->source_positions(), | |
310 SourcePosition::Unknown()); | |
311 ValueNumberingReducer vn_reducer(data->graph_zone()); | |
312 JSTypedLowering lowering(data->jsgraph()); | |
313 SimplifiedOperatorReducer simple_reducer(data->jsgraph()); | |
314 GraphReducer graph_reducer(data->graph()); | |
315 graph_reducer.AddReducer(&vn_reducer); | |
316 graph_reducer.AddReducer(&lowering); | |
317 graph_reducer.AddReducer(&simple_reducer); | |
318 graph_reducer.ReduceGraph(); | |
319 } | |
320 }; | |
321 | |
322 | |
323 struct SimplifiedLoweringPhase { | |
324 void Run(PipelineData* data) { | |
325 PhaseScope phase_scope(data->pipeline_statistics(), "simplified lowering"); | |
326 ZonePool::Scope zone_scope(data->zone_pool()); | |
327 SourcePositionTable::Scope pos(data->source_positions(), | |
328 SourcePosition::Unknown()); | |
329 SimplifiedLowering lowering(data->jsgraph()); | |
330 lowering.LowerAllNodes(); | |
331 ValueNumberingReducer vn_reducer(data->graph_zone()); | |
332 SimplifiedOperatorReducer simple_reducer(data->jsgraph()); | |
333 GraphReducer graph_reducer(data->graph()); | |
334 graph_reducer.AddReducer(&vn_reducer); | |
335 graph_reducer.AddReducer(&simple_reducer); | |
336 graph_reducer.ReduceGraph(); | |
337 } | |
338 }; | |
339 | |
340 | |
341 struct ChangeLoweringPhase { | |
342 void Run(PipelineData* data) { | |
343 PhaseScope phase_scope(data->pipeline_statistics(), "change lowering"); | |
344 ZonePool::Scope zone_scope(data->zone_pool()); | |
345 SourcePositionTable::Scope pos(data->source_positions(), | |
346 SourcePosition::Unknown()); | |
347 Linkage linkage(data->graph_zone(), data->info()); | |
348 ValueNumberingReducer vn_reducer(data->graph_zone()); | |
349 SimplifiedOperatorReducer simple_reducer(data->jsgraph()); | |
350 ChangeLowering lowering(data->jsgraph(), &linkage); | |
351 MachineOperatorReducer mach_reducer(data->jsgraph()); | |
352 GraphReducer graph_reducer(data->graph()); | |
353 // TODO(titzer): Figure out if we should run all reducers at once here. | |
354 graph_reducer.AddReducer(&vn_reducer); | |
355 graph_reducer.AddReducer(&simple_reducer); | |
356 graph_reducer.AddReducer(&lowering); | |
357 graph_reducer.AddReducer(&mach_reducer); | |
358 graph_reducer.ReduceGraph(); | |
359 } | |
360 }; | |
361 | |
362 | |
363 struct ControlReductionPhase { | |
364 void Run(PipelineData* data, const char* phase_name) { | |
365 PhaseScope phase_scope(data->pipeline_statistics(), phase_name); | |
366 ZonePool::Scope zone_scope(data->zone_pool()); | |
367 SourcePositionTable::Scope pos(data->source_positions(), | |
368 SourcePosition::Unknown()); | |
369 ControlReducer::ReduceGraph(zone_scope.zone(), data->jsgraph(), | |
370 data->common()); | |
371 } | |
372 }; | |
373 | |
374 | |
375 struct GenericLoweringPhase { | |
376 void Run(PipelineData* data) { | |
377 PhaseScope phase_scope(data->pipeline_statistics(), "generic lowering"); | |
378 ZonePool::Scope zone_scope(data->zone_pool()); | |
379 SourcePositionTable::Scope pos(data->source_positions(), | |
380 SourcePosition::Unknown()); | |
381 JSGenericLowering generic(data->info(), data->jsgraph()); | |
382 SelectLowering select(data->jsgraph()->graph(), data->jsgraph()->common()); | |
383 GraphReducer graph_reducer(data->graph()); | |
384 graph_reducer.AddReducer(&generic); | |
385 graph_reducer.AddReducer(&select); | |
386 graph_reducer.ReduceGraph(); | |
387 } | |
388 }; | |
389 | |
390 | |
391 struct ComputeSchedulePhase { | |
392 void Run(PipelineData* data) { | |
393 PhaseScope phase_scope(data->pipeline_statistics(), "scheduling"); | |
394 ZonePool::Scope zone_scope(data->zone_pool()); | |
395 Schedule* schedule = | |
396 Scheduler::ComputeSchedule(zone_scope.zone(), data->graph()); | |
397 TraceSchedule(schedule); | |
398 if (VerifyGraphs()) ScheduleVerifier::Run(schedule); | |
399 data->set_schedule(schedule); | |
400 } | |
401 }; | |
402 | |
403 | |
404 struct PrintGraphPhase { | |
405 void Run(PipelineData* data, const char* phase) { | |
406 CompilationInfo* info = data->info(); | |
407 Graph* graph = data->graph(); | |
188 char buffer[256]; | 408 char buffer[256]; |
189 Vector<char> filename(buffer, sizeof(buffer)); | 409 Vector<char> filename(buffer, sizeof(buffer)); |
190 SmartArrayPointer<char> functionname; | 410 SmartArrayPointer<char> functionname; |
191 if (!info_->shared_info().is_null()) { | 411 if (!info->shared_info().is_null()) { |
192 functionname = info_->shared_info()->DebugName()->ToCString(); | 412 functionname = info->shared_info()->DebugName()->ToCString(); |
193 if (strlen(functionname.get()) > 0) { | 413 if (strlen(functionname.get()) > 0) { |
194 SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase); | 414 SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase); |
195 } else { | 415 } else { |
196 SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info_), phase); | 416 SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info), phase); |
197 } | 417 } |
198 } else { | 418 } else { |
199 SNPrintF(filename, "turbo-none-%s", phase); | 419 SNPrintF(filename, "turbo-none-%s", phase); |
200 } | 420 } |
201 std::replace(filename.start(), filename.start() + filename.length(), ' ', | 421 std::replace(filename.start(), filename.start() + filename.length(), ' ', |
202 '_'); | 422 '_'); |
203 | 423 |
204 char dot_buffer[256]; | 424 char dot_buffer[256]; |
205 Vector<char> dot_filename(dot_buffer, sizeof(dot_buffer)); | 425 Vector<char> dot_filename(dot_buffer, sizeof(dot_buffer)); |
206 SNPrintF(dot_filename, "%s.dot", filename.start()); | 426 SNPrintF(dot_filename, "%s.dot", filename.start()); |
207 FILE* dot_file = base::OS::FOpen(dot_filename.start(), "w+"); | 427 FILE* dot_file = base::OS::FOpen(dot_filename.start(), "w+"); |
208 OFStream dot_of(dot_file); | 428 OFStream dot_of(dot_file); |
209 dot_of << AsDOT(*graph); | 429 dot_of << AsDOT(*graph); |
210 fclose(dot_file); | 430 fclose(dot_file); |
211 | 431 |
212 char json_buffer[256]; | 432 char json_buffer[256]; |
213 Vector<char> json_filename(json_buffer, sizeof(json_buffer)); | 433 Vector<char> json_filename(json_buffer, sizeof(json_buffer)); |
214 SNPrintF(json_filename, "%s.json", filename.start()); | 434 SNPrintF(json_filename, "%s.json", filename.start()); |
215 FILE* json_file = base::OS::FOpen(json_filename.start(), "w+"); | 435 FILE* json_file = base::OS::FOpen(json_filename.start(), "w+"); |
216 OFStream json_of(json_file); | 436 OFStream json_of(json_file); |
217 json_of << AsJSON(*graph); | 437 json_of << AsJSON(*graph); |
218 fclose(json_file); | 438 fclose(json_file); |
219 | 439 |
220 OFStream os(stdout); | 440 OFStream os(stdout); |
221 os << "-- " << phase << " graph printed to file " << filename.start() | 441 os << "-- " << phase << " graph printed to file " << filename.start() |
222 << "\n"; | 442 << "\n"; |
223 } | 443 } |
444 }; | |
445 | |
446 | |
447 struct VerifyGraphPhase { | |
448 void Run(PipelineData* data, const bool untyped) { | |
449 Verifier::Run(data->graph(), FLAG_turbo_types && !untyped | |
450 ? Verifier::TYPED | |
451 : Verifier::UNTYPED); | |
452 } | |
453 }; | |
454 | |
455 | |
456 void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { | |
457 if (FLAG_trace_turbo) { | |
458 Run<PrintGraphPhase>(phase); | |
459 } | |
224 if (VerifyGraphs()) { | 460 if (VerifyGraphs()) { |
225 Verifier::Run(graph, | 461 Run<VerifyGraphPhase>(untyped); |
226 FLAG_turbo_types && !untyped ? Verifier::TYPED : Verifier::UNTYPED); | |
227 } | 462 } |
228 } | 463 } |
229 | 464 |
230 | 465 |
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() { | 466 Handle<Code> Pipeline::GenerateCode() { |
285 // This list must be kept in sync with DONT_TURBOFAN_NODE in ast.cc. | 467 // This list must be kept in sync with DONT_TURBOFAN_NODE in ast.cc. |
286 if (info()->function()->dont_optimize_reason() == kTryCatchStatement || | 468 if (info()->function()->dont_optimize_reason() == kTryCatchStatement || |
287 info()->function()->dont_optimize_reason() == kTryFinallyStatement || | 469 info()->function()->dont_optimize_reason() == kTryFinallyStatement || |
288 // TODO(turbofan): Make ES6 for-of work and remove this bailout. | 470 // TODO(turbofan): Make ES6 for-of work and remove this bailout. |
289 info()->function()->dont_optimize_reason() == kForOfStatement || | 471 info()->function()->dont_optimize_reason() == kForOfStatement || |
290 // TODO(turbofan): Make super work and remove this bailout. | 472 // TODO(turbofan): Make super work and remove this bailout. |
291 info()->function()->dont_optimize_reason() == kSuperReference || | 473 info()->function()->dont_optimize_reason() == kSuperReference || |
292 // TODO(turbofan): Make class literals work and remove this bailout. | 474 // TODO(turbofan): Make class literals work and remove this bailout. |
293 info()->function()->dont_optimize_reason() == kClassLiteral || | 475 info()->function()->dont_optimize_reason() == kClassLiteral || |
294 // TODO(turbofan): Make OSR work and remove this bailout. | 476 // TODO(turbofan): Make OSR work and remove this bailout. |
295 info()->is_osr()) { | 477 info()->is_osr()) { |
296 return Handle<Code>::null(); | 478 return Handle<Code>::null(); |
297 } | 479 } |
298 | 480 |
299 ZonePool zone_pool(isolate()); | 481 ZonePool zone_pool(isolate()); |
482 SmartPointer<PipelineStatistics> pipeline_statistics; | |
300 | 483 |
301 SmartPointer<PipelineStatistics> pipeline_statistics; | |
302 if (FLAG_turbo_stats) { | 484 if (FLAG_turbo_stats) { |
303 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); | 485 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); |
304 pipeline_statistics->BeginPhaseKind("graph creation"); | 486 pipeline_statistics->BeginPhaseKind("graph creation"); |
305 } | 487 } |
306 | 488 |
489 PipelineData data(info(), &zone_pool, pipeline_statistics.get()); | |
490 this->data_ = &data; | |
491 | |
307 if (FLAG_trace_turbo) { | 492 if (FLAG_trace_turbo) { |
308 OFStream os(stdout); | 493 OFStream os(stdout); |
309 os << "---------------------------------------------------\n" | 494 os << "---------------------------------------------------\n" |
310 << "Begin compiling method " << GetDebugName(info()).get() | 495 << "Begin compiling method " << GetDebugName(info()).get() |
311 << " using Turbofan" << std::endl; | 496 << " using Turbofan" << std::endl; |
312 TurboCfgFile tcf(isolate()); | 497 TurboCfgFile tcf(isolate()); |
313 tcf << AsC1VCompilation(info()); | 498 tcf << AsC1VCompilation(info()); |
314 } | 499 } |
315 | 500 |
316 // Initialize the graph and builders. | |
317 PipelineData data(info(), &zone_pool, pipeline_statistics.get()); | |
318 | |
319 data.source_positions()->AddDecorator(); | 501 data.source_positions()->AddDecorator(); |
320 | 502 |
321 Node* context_node; | 503 Run<GraphBuilderPhase>(); |
322 { | 504 if (data.compilation_failed()) return Handle<Code>::null(); |
323 PhaseScope phase_scope(pipeline_statistics.get(), "graph builder"); | 505 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 | 506 |
331 VerifyAndPrintGraph(data.graph(), "Initial untyped", true); | 507 Run<ControlReductionPhase>("early control reduction"); |
332 | 508 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 | 509 |
345 if (info()->is_context_specializing()) { | 510 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. | 511 // Specialize the code to the context as aggressively as possible. |
349 JSContextSpecializer spec(info(), data.jsgraph(), context_node); | 512 Run<ContextSpecializerPhase>(); |
350 spec.SpecializeToContext(); | 513 RunPrintAndVerify("Context specialized", true); |
351 VerifyAndPrintGraph(data.graph(), "Context specialized", true); | |
352 } | 514 } |
353 | 515 |
354 if (info()->is_inlining_enabled()) { | 516 if (info()->is_inlining_enabled()) { |
355 PhaseScope phase_scope(pipeline_statistics.get(), "inlining"); | 517 Run<InliningPhase>(); |
356 SourcePositionTable::Scope pos(data.source_positions(), | 518 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 } | 519 } |
363 | 520 |
364 // Print a replay of the initial graph. | |
365 if (FLAG_print_turbo_replay) { | 521 if (FLAG_print_turbo_replay) { |
522 // Print a replay of the initial graph. | |
366 GraphReplayPrinter::PrintReplay(data.graph()); | 523 GraphReplayPrinter::PrintReplay(data.graph()); |
367 } | 524 } |
368 | 525 |
369 // Bailout here in case target architecture is not supported. | 526 // Bailout here in case target architecture is not supported. |
370 if (!SupportedTarget()) return Handle<Code>::null(); | 527 if (!SupportedTarget()) return Handle<Code>::null(); |
371 | 528 |
372 if (info()->is_typing_enabled()) { | 529 if (info()->is_typing_enabled()) { |
373 { | 530 // Type the graph. |
374 // Type the graph. | 531 Run<TyperPhase>(); |
375 PhaseScope phase_scope(pipeline_statistics.get(), "typer"); | 532 RunPrintAndVerify("Typed"); |
376 data.typer()->Run(); | |
377 VerifyAndPrintGraph(data.graph(), "Typed"); | |
378 } | |
379 } | 533 } |
380 | 534 |
381 if (!pipeline_statistics.is_empty()) { | 535 if (!pipeline_statistics.is_empty()) { |
382 pipeline_statistics->BeginPhaseKind("lowering"); | 536 data.pipeline_statistics()->BeginPhaseKind("lowering"); |
383 } | 537 } |
384 | 538 |
385 if (info()->is_typing_enabled()) { | 539 if (info()->is_typing_enabled()) { |
386 { | 540 // Lower JSOperators where we can determine types. |
387 // Lower JSOperators where we can determine types. | 541 Run<TypedLoweringPhase>(); |
388 PhaseScope phase_scope(pipeline_statistics.get(), "typed lowering"); | 542 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 | 543 |
400 VerifyAndPrintGraph(data.graph(), "Lowered typed"); | 544 // Lower simplified operators and insert changes. |
401 } | 545 Run<SimplifiedLoweringPhase>(); |
402 { | 546 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 | 547 |
416 VerifyAndPrintGraph(data.graph(), "Lowered simplified"); | 548 // Lower changes that have been inserted before. |
417 } | 549 Run<ChangeLoweringPhase>(); |
418 { | 550 // // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
419 // Lower changes that have been inserted before. | 551 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 | 552 |
436 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 553 Run<ControlReductionPhase>("late control reduction"); |
437 VerifyAndPrintGraph(data.graph(), "Lowered changes", true); | 554 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 } | 555 } |
452 | 556 |
453 { | 557 // Lower any remaining generic JSOperators. |
454 // Lower any remaining generic JSOperators. | 558 Run<GenericLoweringPhase>(); |
455 PhaseScope phase_scope(pipeline_statistics.get(), "generic lowering"); | 559 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
456 SourcePositionTable::Scope pos(data.source_positions(), | 560 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 | 561 |
469 if (!pipeline_statistics.is_empty()) { | 562 if (!pipeline_statistics.is_empty()) { |
470 pipeline_statistics->BeginPhaseKind("block building"); | 563 data.pipeline_statistics()->BeginPhaseKind("block building"); |
471 } | 564 } |
472 | 565 |
473 data.source_positions()->RemoveDecorator(); | 566 data.source_positions()->RemoveDecorator(); |
474 | 567 |
475 // Compute a schedule. | 568 // Compute a schedule. |
476 ComputeSchedule(&data); | 569 Run<ComputeSchedulePhase>(); |
477 | 570 |
478 Handle<Code> code = Handle<Code>::null(); | 571 Handle<Code> code = Handle<Code>::null(); |
479 { | 572 { |
480 // Generate optimized code. | 573 // Generate optimized code. |
481 Linkage linkage(data.instruction_zone(), info()); | 574 Linkage linkage(data.instruction_zone(), info()); |
482 code = GenerateCode(&linkage, &data); | 575 code = GenerateCode(&linkage, &data); |
483 info()->SetCode(code); | 576 info()->SetCode(code); |
484 } | 577 } |
485 | 578 |
486 // Print optimized code. | 579 // Print optimized code. |
487 v8::internal::CodeGenerator::PrintCode(code, info()); | 580 v8::internal::CodeGenerator::PrintCode(code, info()); |
488 | 581 |
489 if (FLAG_trace_turbo) { | 582 if (FLAG_trace_turbo) { |
490 OFStream os(stdout); | 583 OFStream os(stdout); |
491 os << "--------------------------------------------------\n" | 584 os << "--------------------------------------------------\n" |
492 << "Finished compiling method " << GetDebugName(info()).get() | 585 << "Finished compiling method " << GetDebugName(info()).get() |
493 << " using Turbofan" << std::endl; | 586 << " using Turbofan" << std::endl; |
494 } | 587 } |
495 | 588 |
496 return code; | 589 return code; |
497 } | 590 } |
498 | 591 |
499 | 592 |
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, | 593 Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
512 Graph* graph, | 594 Graph* graph, |
513 Schedule* schedule) { | 595 Schedule* schedule) { |
514 ZonePool zone_pool(isolate()); | 596 ZonePool zone_pool(isolate()); |
515 CHECK(SupportedBackend()); | 597 CHECK(SupportedBackend()); |
516 PipelineData data(graph, schedule, &zone_pool); | 598 PipelineData data(graph, schedule, &zone_pool); |
599 this->data_ = &data; | |
517 if (schedule == NULL) { | 600 if (schedule == NULL) { |
518 // TODO(rossberg): Should this really be untyped? | 601 // TODO(rossberg): Should this really be untyped? |
519 VerifyAndPrintGraph(graph, "Machine", true); | 602 RunPrintAndVerify("Machine", true); |
520 ComputeSchedule(&data); | 603 Run<ComputeSchedulePhase>(); |
521 } else { | 604 } else { |
522 TraceSchedule(schedule); | 605 TraceSchedule(schedule); |
523 } | 606 } |
524 | 607 |
525 Handle<Code> code = GenerateCode(linkage, &data); | 608 Handle<Code> code = GenerateCode(linkage, &data); |
526 #if ENABLE_DISASSEMBLER | 609 #if ENABLE_DISASSEMBLER |
527 if (!code.is_null() && FLAG_print_opt_code) { | 610 if (!code.is_null() && FLAG_print_opt_code) { |
528 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); | 611 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); |
529 OFStream os(tracing_scope.file()); | 612 OFStream os(tracing_scope.file()); |
530 code->Disassemble("test code", os); | 613 code->Disassemble("test code", os); |
(...skipping 117 matching lines...) Loading... | |
648 } | 731 } |
649 | 732 |
650 | 733 |
651 void Pipeline::TearDown() { | 734 void Pipeline::TearDown() { |
652 InstructionOperand::TearDownCaches(); | 735 InstructionOperand::TearDownCaches(); |
653 } | 736 } |
654 | 737 |
655 } // namespace compiler | 738 } // namespace compiler |
656 } // namespace internal | 739 } // namespace internal |
657 } // namespace v8 | 740 } // namespace v8 |
OLD | NEW |