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