OLD | NEW |
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/compiler.h" | 5 #include "vm/compiler.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 | 8 |
9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
10 #include "vm/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 "Print the IR flow graph when optimizing."); | 56 "Print the IR flow graph when optimizing."); |
57 DEFINE_FLAG(bool, print_ic_data_map, false, | 57 DEFINE_FLAG(bool, print_ic_data_map, false, |
58 "Print the deopt-id to ICData map in optimizing compiler."); | 58 "Print the deopt-id to ICData map in optimizing compiler."); |
59 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); | 59 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); |
60 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering."); | 60 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering."); |
61 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); | 61 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); |
62 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); | 62 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); |
63 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); | 63 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); |
64 DEFINE_FLAG(bool, verify_compiler, false, | 64 DEFINE_FLAG(bool, verify_compiler, false, |
65 "Enable compiler verification assertions"); | 65 "Enable compiler verification assertions"); |
| 66 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, |
| 67 "Max number of attempts with speculative inlining (precompilation only)"); |
66 | 68 |
67 DECLARE_FLAG(bool, background_compilation); | 69 DECLARE_FLAG(bool, background_compilation); |
68 DECLARE_FLAG(bool, load_deferred_eagerly); | 70 DECLARE_FLAG(bool, load_deferred_eagerly); |
69 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 71 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
70 DECLARE_FLAG(bool, trace_inlining_intervals); | 72 DECLARE_FLAG(bool, trace_inlining_intervals); |
71 DECLARE_FLAG(bool, trace_irregexp); | 73 DECLARE_FLAG(bool, trace_irregexp); |
72 | 74 |
73 | 75 |
74 bool Compiler::always_optimize_ = false; | 76 bool Compiler::always_optimize_ = false; |
75 bool Compiler::allow_recompilation_ = true; | 77 bool Compiler::allow_recompilation_ = true; |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 | 407 |
406 // We may reattempt compilation if the function needs to be assembled using | 408 // We may reattempt compilation if the function needs to be assembled using |
407 // far branches on ARM and MIPS. In the else branch of the setjmp call, | 409 // far branches on ARM and MIPS. In the else branch of the setjmp call, |
408 // done is set to false, and use_far_branches is set to true if there is a | 410 // done is set to false, and use_far_branches is set to true if there is a |
409 // longjmp from the ARM or MIPS assemblers. In all other paths through this | 411 // longjmp from the ARM or MIPS assemblers. In all other paths through this |
410 // while loop, done is set to true. use_far_branches is always false on ia32 | 412 // while loop, done is set to true. use_far_branches is always false on ia32 |
411 // and x64. | 413 // and x64. |
412 bool done = false; | 414 bool done = false; |
413 // volatile because the variable may be clobbered by a longjmp. | 415 // volatile because the variable may be clobbered by a longjmp. |
414 volatile bool use_far_branches = false; | 416 volatile bool use_far_branches = false; |
| 417 volatile bool use_speculative_inlining = true; |
| 418 GrowableArray<intptr_t> inlining_black_list; |
| 419 |
415 while (!done) { | 420 while (!done) { |
416 const intptr_t prev_deopt_id = thread->deopt_id(); | 421 const intptr_t prev_deopt_id = thread->deopt_id(); |
417 thread->set_deopt_id(0); | 422 thread->set_deopt_id(0); |
418 LongJumpScope jump; | 423 LongJumpScope jump; |
419 if (setjmp(*jump.Set()) == 0) { | 424 const intptr_t val = setjmp(*jump.Set()); |
| 425 if (val == 0) { |
420 FlowGraph* flow_graph = NULL; | 426 FlowGraph* flow_graph = NULL; |
421 | 427 |
422 // Class hierarchy analysis is registered with the isolate in the | 428 // Class hierarchy analysis is registered with the isolate in the |
423 // constructor and unregisters itself upon destruction. | 429 // constructor and unregisters itself upon destruction. |
424 CHA cha(thread); | 430 CHA cha(thread); |
425 | 431 |
426 // TimerScope needs an isolate to be properly terminated in case of a | 432 // TimerScope needs an isolate to be properly terminated in case of a |
427 // LongJump. | 433 // LongJump. |
428 { | 434 { |
429 CSTAT_TIMER_SCOPE(thread, graphbuilder_timer); | 435 CSTAT_TIMER_SCOPE(thread, graphbuilder_timer); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 GrowableArray<intptr_t> caller_inline_id; | 499 GrowableArray<intptr_t> caller_inline_id; |
494 // Collect all instance fields that are loaded in the graph and | 500 // Collect all instance fields that are loaded in the graph and |
495 // have non-generic type feedback attached to them that can | 501 // have non-generic type feedback attached to them that can |
496 // potentially affect optimizations. | 502 // potentially affect optimizations. |
497 if (optimized) { | 503 if (optimized) { |
498 inline_id_to_function.Add(&function); | 504 inline_id_to_function.Add(&function); |
499 // Top scope function has no caller (-1). | 505 // Top scope function has no caller (-1). |
500 caller_inline_id.Add(-1); | 506 caller_inline_id.Add(-1); |
501 CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer); | 507 CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer); |
502 | 508 |
503 FlowGraphOptimizer optimizer(flow_graph); | 509 FlowGraphOptimizer optimizer(flow_graph, |
| 510 use_speculative_inlining, |
| 511 &inlining_black_list); |
504 if (Compiler::always_optimize()) { | 512 if (Compiler::always_optimize()) { |
505 optimizer.PopulateWithICData(); | 513 optimizer.PopulateWithICData(); |
| 514 |
| 515 optimizer.ApplyClassIds(); |
| 516 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 517 |
| 518 FlowGraphTypePropagator::Propagate(flow_graph); |
| 519 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
506 } | 520 } |
507 optimizer.ApplyICData(); | 521 optimizer.ApplyICData(); |
508 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 522 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
509 | 523 |
510 // Optimize (a << b) & c patterns, merge operations. | 524 // Optimize (a << b) & c patterns, merge operations. |
511 // Run early in order to have more opportunity to optimize left shifts. | 525 // Run early in order to have more opportunity to optimize left shifts. |
512 optimizer.TryOptimizePatterns(); | 526 optimizer.TryOptimizePatterns(); |
513 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 527 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
514 | 528 |
515 FlowGraphInliner::SetInliningId(flow_graph, 0); | 529 FlowGraphInliner::SetInliningId(flow_graph, 0); |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 // We bailed out or we encountered an error. | 877 // We bailed out or we encountered an error. |
864 const Error& error = Error::Handle( | 878 const Error& error = Error::Handle( |
865 isolate->object_store()->sticky_error()); | 879 isolate->object_store()->sticky_error()); |
866 | 880 |
867 if (error.raw() == Object::branch_offset_error().raw()) { | 881 if (error.raw() == Object::branch_offset_error().raw()) { |
868 // Compilation failed due to an out of range branch offset in the | 882 // Compilation failed due to an out of range branch offset in the |
869 // assembler. We try again (done = false) with far branches enabled. | 883 // assembler. We try again (done = false) with far branches enabled. |
870 done = false; | 884 done = false; |
871 ASSERT(!use_far_branches); | 885 ASSERT(!use_far_branches); |
872 use_far_branches = true; | 886 use_far_branches = true; |
| 887 } else if (error.raw() == Object::speculative_inlining_error().raw()) { |
| 888 // The return value of setjmp is the deopt id of the check instruction |
| 889 // that caused the bailout. |
| 890 done = false; |
| 891 #if defined(DEBUG) |
| 892 ASSERT(Compiler::always_optimize()); |
| 893 ASSERT(use_speculative_inlining); |
| 894 for (intptr_t i = 0; i < inlining_black_list.length(); ++i) { |
| 895 ASSERT(inlining_black_list[i] != val); |
| 896 } |
| 897 #endif |
| 898 inlining_black_list.Add(val); |
| 899 const intptr_t max_attempts = FLAG_max_speculative_inlining_attempts; |
| 900 if (inlining_black_list.length() >= max_attempts) { |
| 901 use_speculative_inlining = false; |
| 902 if (FLAG_trace_compiler) { |
| 903 THR_Print("Disabled speculative inlining after %" Pd " attempts.\n", |
| 904 inlining_black_list.length()); |
| 905 } |
| 906 } |
873 } else { | 907 } else { |
874 // If the error isn't due to an out of range branch offset, we don't | 908 // If the error isn't due to an out of range branch offset, we don't |
875 // try again (done = true), and indicate that we did not finish | 909 // try again (done = true), and indicate that we did not finish |
876 // compiling (is_compiled = false). | 910 // compiling (is_compiled = false). |
877 if (FLAG_trace_bailout) { | 911 if (FLAG_trace_bailout) { |
878 THR_Print("%s\n", error.ToErrorCString()); | 912 THR_Print("%s\n", error.ToErrorCString()); |
879 } | 913 } |
880 done = true; | 914 done = true; |
881 } | 915 } |
882 | 916 |
(...skipping 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1965 isolate->set_background_compiler(task); | 1999 isolate->set_background_compiler(task); |
1966 start_task = true; | 2000 start_task = true; |
1967 } | 2001 } |
1968 } | 2002 } |
1969 if (start_task) { | 2003 if (start_task) { |
1970 Dart::thread_pool()->Run(isolate->background_compiler()); | 2004 Dart::thread_pool()->Run(isolate->background_compiler()); |
1971 } | 2005 } |
1972 } | 2006 } |
1973 | 2007 |
1974 } // namespace dart | 2008 } // namespace dart |
OLD | NEW |