Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: runtime/vm/flow_graph_inliner.cc

Issue 11231065: Cleanups in the inliner. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/compiler.h" 7 #include "vm/compiler.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/flow_graph.h" 9 #include "vm/flow_graph.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
11 #include "vm/flow_graph_optimizer.h" 11 #include "vm/flow_graph_optimizer.h"
12 #include "vm/il_printer.h" 12 #include "vm/il_printer.h"
13 #include "vm/intrinsifier.h" 13 #include "vm/intrinsifier.h"
14 #include "vm/longjump.h" 14 #include "vm/longjump.h"
15 #include "vm/object.h" 15 #include "vm/object.h"
16 #include "vm/object_store.h" 16 #include "vm/object_store.h"
17 17
18 namespace dart { 18 namespace dart {
19 19
20 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining"); 20 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
21 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function"); 21 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
22 DEFINE_FLAG(int, inlining_size_threshold, 50, 22 DEFINE_FLAG(int, inlining_size_threshold, 50,
23 "Inline only functions with up to threshold instructions (default 50)"); 23 "Inline only functions with up to threshold instructions (default 50)");
24 // TODO(srdjan): set to 3 once crash in apidoc.dart is resolved. 24 // TODO(srdjan): set to 3 once crash in apidoc.dart is resolved.
25 DEFINE_FLAG(int, inlining_depth_threshold, 3, 25 DEFINE_FLAG(int, inlining_depth_threshold, 3,
26 "Inline recursively up to threshold depth (default 3)"); 26 "Inline recursively up to threshold depth (default 3)");
27 DEFINE_FLAG(bool, inline_control_flow, true,
28 "Inline functions with control flow.");
29 DECLARE_FLAG(bool, print_flow_graph); 27 DECLARE_FLAG(bool, print_flow_graph);
30 DECLARE_FLAG(int, deoptimization_counter_threshold); 28 DECLARE_FLAG(int, deoptimization_counter_threshold);
31 DECLARE_FLAG(bool, verify_compiler); 29 DECLARE_FLAG(bool, verify_compiler);
32 30
33 #define TRACE_INLINING(statement) \ 31 #define TRACE_INLINING(statement) \
34 do { \ 32 do { \
35 if (FLAG_trace_inlining) statement; \ 33 if (FLAG_trace_inlining) statement; \
36 } while (false) 34 } while (false)
37 35
38 36
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 public: 163 public:
166 explicit CallSiteInliner(FlowGraph* flow_graph) 164 explicit CallSiteInliner(FlowGraph* flow_graph)
167 : caller_graph_(flow_graph), 165 : caller_graph_(flow_graph),
168 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), 166 next_ssa_temp_index_(flow_graph->max_virtual_register_number()),
169 inlined_(false), 167 inlined_(false),
170 initial_size_(flow_graph->InstructionCount()), 168 initial_size_(flow_graph->InstructionCount()),
171 inlined_size_(0), 169 inlined_size_(0),
172 inlining_depth_(1), 170 inlining_depth_(1),
173 collected_call_sites_(NULL), 171 collected_call_sites_(NULL),
174 inlining_call_sites_(NULL), 172 inlining_call_sites_(NULL),
175 function_cache() { } 173 function_cache_() { }
176 174
177 void InlineCalls() { 175 void InlineCalls() {
178 // If inlining depth is less then one abort. 176 // If inlining depth is less then one abort.
179 if (FLAG_inlining_depth_threshold < 1) return; 177 if (FLAG_inlining_depth_threshold < 1) return;
180 // Create two call site collections to swap between. 178 // Create two call site collections to swap between.
181 CallSites sites1(caller_graph_); 179 CallSites sites1(caller_graph_);
182 CallSites sites2(caller_graph_); 180 CallSites sites2(caller_graph_);
183 CallSites* call_sites_temp = NULL; 181 CallSites* call_sites_temp = NULL;
184 collected_call_sites_ = &sites1; 182 collected_call_sites_ = &sites1;
185 inlining_call_sites_ = &sites2; 183 inlining_call_sites_ = &sites2;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 // Save and clear deopt id. 260 // Save and clear deopt id.
263 const intptr_t prev_deopt_id = isolate->deopt_id(); 261 const intptr_t prev_deopt_id = isolate->deopt_id();
264 isolate->set_deopt_id(0); 262 isolate->set_deopt_id(0);
265 // Install bailout jump. 263 // Install bailout jump.
266 LongJump* base = isolate->long_jump_base(); 264 LongJump* base = isolate->long_jump_base();
267 LongJump jump; 265 LongJump jump;
268 isolate->set_long_jump_base(&jump); 266 isolate->set_long_jump_base(&jump);
269 if (setjmp(*jump.Set()) == 0) { 267 if (setjmp(*jump.Set()) == 0) {
270 // Parse the callee function. 268 // Parse the callee function.
271 bool in_cache; 269 bool in_cache;
272 ParsedFunction* parsed_function = ParseFunction(function, &in_cache); 270 ParsedFunction* parsed_function = GetParsedFunction(function, &in_cache);
273 271
274 // Load IC data for the callee. 272 // Load IC data for the callee.
275 if (function.HasCode()) { 273 if (function.HasCode()) {
276 const Code& unoptimized_code = 274 const Code& unoptimized_code =
277 Code::Handle(function.unoptimized_code()); 275 Code::Handle(function.unoptimized_code());
278 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray()); 276 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray());
279 } 277 }
280 278
281 // Build the callee graph. 279 // Build the callee graph.
282 FlowGraphBuilder builder(*parsed_function); 280 FlowGraphBuilder builder(*parsed_function);
283 builder.SetInitialBlockId(caller_graph_->max_block_id()); 281 builder.SetInitialBlockId(caller_graph_->max_block_id());
284 FlowGraph* callee_graph = 282 FlowGraph* callee_graph =
285 builder.BuildGraph(FlowGraphBuilder::kValueContext); 283 builder.BuildGraph(FlowGraphBuilder::kValueContext);
286 284
287 // Abort if the callee graph contains control flow.
288 if (!FLAG_inline_control_flow &&
289 (callee_graph->preorder().length() != 2)) {
290 function.set_is_inlinable(false);
291 isolate->set_long_jump_base(base);
292 isolate->set_ic_data_array(prev_ic_data.raw());
293 TRACE_INLINING(OS::Print(" Bailout: control flow\n"));
294 return false;
295 }
296
297 // Compute SSA on the callee graph, catching bailouts. 285 // Compute SSA on the callee graph, catching bailouts.
298 callee_graph->ComputeSSA(next_ssa_temp_index_); 286 callee_graph->ComputeSSA(next_ssa_temp_index_);
299 callee_graph->ComputeUseLists(); 287 callee_graph->ComputeUseLists();
300 288
301 // TODO(zerny): Do more optimization passes on the callee graph. 289 // TODO(zerny): Do more optimization passes on the callee graph.
302 FlowGraphOptimizer optimizer(callee_graph); 290 FlowGraphOptimizer optimizer(callee_graph);
303 optimizer.ApplyICData(); 291 optimizer.ApplyICData();
304 callee_graph->ComputeUseLists(); 292 callee_graph->ComputeUseLists();
305 293
306 if (FLAG_trace_inlining && FLAG_print_flow_graph) { 294 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 } 338 }
351 ASSERT(arg_index == arguments->length()); 339 ASSERT(arg_index == arguments->length());
352 340
353 // Replace callee's null constant with caller's null constant. 341 // Replace callee's null constant with caller's null constant.
354 callee_graph->graph_entry()->constant_null()->ReplaceUsesWith( 342 callee_graph->graph_entry()->constant_null()->ReplaceUsesWith(
355 caller_graph_->graph_entry()->constant_null()); 343 caller_graph_->graph_entry()->constant_null());
356 344
357 TRACE_INLINING(OS::Print(" Success\n")); 345 TRACE_INLINING(OS::Print(" Success\n"));
358 346
359 // Add the function to the cache. 347 // Add the function to the cache.
360 if (!in_cache) function_cache.Add(parsed_function); 348 if (!in_cache) function_cache_.Add(parsed_function);
361 349
362 // Check that inlining maintains use lists. 350 // Check that inlining maintains use lists.
363 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->ValidateUseLists()); 351 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->ValidateUseLists());
364 352
365 // Build succeeded so we restore the bailout jump. 353 // Build succeeded so we restore the bailout jump.
366 inlined_ = true; 354 inlined_ = true;
367 inlined_size_ += size; 355 inlined_size_ += size;
368 isolate->set_long_jump_base(base); 356 isolate->set_long_jump_base(base);
369 isolate->set_deopt_id(prev_deopt_id); 357 isolate->set_deopt_id(prev_deopt_id);
370 isolate->set_ic_data_array(prev_ic_data.raw()); 358 isolate->set_ic_data_array(prev_ic_data.raw());
371 return true; 359 return true;
372 } else { 360 } else {
373 Error& error = Error::Handle(); 361 Error& error = Error::Handle();
374 error = isolate->object_store()->sticky_error(); 362 error = isolate->object_store()->sticky_error();
375 isolate->object_store()->clear_sticky_error(); 363 isolate->object_store()->clear_sticky_error();
376 isolate->set_long_jump_base(base); 364 isolate->set_long_jump_base(base);
377 isolate->set_deopt_id(prev_deopt_id); 365 isolate->set_deopt_id(prev_deopt_id);
378 isolate->set_ic_data_array(prev_ic_data.raw()); 366 isolate->set_ic_data_array(prev_ic_data.raw());
379 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); 367 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString()));
380 return false; 368 return false;
381 } 369 }
382 } 370 }
383 371
384 // Parse a function reusing the cache if possible. Returns true if the 372 // Parse a function reusing the cache if possible. Returns true if the
385 // function was in the cache. 373 // function was in the cache.
386 ParsedFunction* ParseFunction(const Function& function, bool* in_cache) { 374 ParsedFunction* GetParsedFunction(const Function& function, bool* in_cache) {
387 // TODO(zerny): Use a hash map for the cache. 375 // TODO(zerny): Use a hash map for the cache.
388 for (intptr_t i = 0; i < function_cache.length(); ++i) { 376 for (intptr_t i = 0; i < function_cache_.length(); ++i) {
389 ParsedFunction* parsed_function = function_cache[i]; 377 ParsedFunction* parsed_function = function_cache_[i];
390 if (parsed_function->function().raw() == function.raw()) { 378 if (parsed_function->function().raw() == function.raw()) {
391 *in_cache = true; 379 *in_cache = true;
392 SourceLabelResetter reset; 380 SourceLabelResetter reset;
393 parsed_function->node_sequence()->Visit(&reset); 381 parsed_function->node_sequence()->Visit(&reset);
394 return parsed_function; 382 return parsed_function;
395 } 383 }
396 } 384 }
397 *in_cache = false; 385 *in_cache = false;
398 ParsedFunction* parsed_function = new ParsedFunction(function); 386 ParsedFunction* parsed_function = new ParsedFunction(function);
399 Parser::ParseFunction(parsed_function); 387 Parser::ParseFunction(parsed_function);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 } 451 }
464 452
465 FlowGraph* caller_graph_; 453 FlowGraph* caller_graph_;
466 intptr_t next_ssa_temp_index_; 454 intptr_t next_ssa_temp_index_;
467 bool inlined_; 455 bool inlined_;
468 intptr_t initial_size_; 456 intptr_t initial_size_;
469 intptr_t inlined_size_; 457 intptr_t inlined_size_;
470 intptr_t inlining_depth_; 458 intptr_t inlining_depth_;
471 CallSites* collected_call_sites_; 459 CallSites* collected_call_sites_;
472 CallSites* inlining_call_sites_; 460 CallSites* inlining_call_sites_;
473 GrowableArray<ParsedFunction*> function_cache; 461 GrowableArray<ParsedFunction*> function_cache_;
474 462
475 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); 463 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner);
476 }; 464 };
477 465
478 466
479 void FlowGraphInliner::Inline() { 467 void FlowGraphInliner::Inline() {
480 if ((FLAG_inlining_filter != NULL) && 468 if ((FLAG_inlining_filter != NULL) &&
481 (strstr(flow_graph_-> 469 (strstr(flow_graph_->
482 parsed_function().function().ToFullyQualifiedCString(), 470 parsed_function().function().ToFullyQualifiedCString(),
483 FLAG_inlining_filter) == NULL)) { 471 FLAG_inlining_filter) == NULL)) {
(...skipping 21 matching lines...) Expand all
505 OS::Print("After Inlining of %s\n", flow_graph_-> 493 OS::Print("After Inlining of %s\n", flow_graph_->
506 parsed_function().function().ToFullyQualifiedCString()); 494 parsed_function().function().ToFullyQualifiedCString());
507 FlowGraphPrinter printer(*flow_graph_); 495 FlowGraphPrinter printer(*flow_graph_);
508 printer.PrintBlocks(); 496 printer.PrintBlocks();
509 } 497 }
510 } 498 }
511 } 499 }
512 } 500 }
513 501
514 } // namespace dart 502 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698