Index: runtime/vm/compiler.cc |
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc |
index f3d879a8c90bf2a28d645b2b1974441517858ac5..917d481abd6cac077d15e240286297e09e952920 100644 |
--- a/runtime/vm/compiler.cc |
+++ b/runtime/vm/compiler.cc |
@@ -63,6 +63,8 @@ DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); |
DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); |
DEFINE_FLAG(bool, verify_compiler, false, |
"Enable compiler verification assertions"); |
+DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, |
+ "Max number of attempts with speculative inlining (precompilation only)"); |
DECLARE_FLAG(bool, background_compilation); |
DECLARE_FLAG(bool, load_deferred_eagerly); |
@@ -412,11 +414,15 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
bool done = false; |
// volatile because the variable may be clobbered by a longjmp. |
volatile bool use_far_branches = false; |
+ volatile bool use_speculative_inlining = true; |
+ GrowableArray<intptr_t> inlining_black_list; |
+ |
while (!done) { |
const intptr_t prev_deopt_id = thread->deopt_id(); |
thread->set_deopt_id(0); |
LongJumpScope jump; |
- if (setjmp(*jump.Set()) == 0) { |
+ const intptr_t val = setjmp(*jump.Set()); |
+ if (val == 0) { |
FlowGraph* flow_graph = NULL; |
// Class hierarchy analysis is registered with the isolate in the |
@@ -500,9 +506,17 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
caller_inline_id.Add(-1); |
CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer); |
- FlowGraphOptimizer optimizer(flow_graph); |
+ FlowGraphOptimizer optimizer(flow_graph, |
+ use_speculative_inlining, |
+ &inlining_black_list); |
if (Compiler::always_optimize()) { |
optimizer.PopulateWithICData(); |
+ |
+ optimizer.ApplyClassIds(); |
+ DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
+ |
+ FlowGraphTypePropagator::Propagate(flow_graph); |
+ DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
} |
optimizer.ApplyICData(); |
DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
@@ -870,6 +884,26 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
done = false; |
ASSERT(!use_far_branches); |
use_far_branches = true; |
+ } else if (error.raw() == Object::speculative_inlining_error().raw()) { |
+ // The return value of setjmp is the deopt id of the check instruction |
+ // that caused the bailout. |
+ done = false; |
+#if defined(DEBUG) |
+ ASSERT(Compiler::always_optimize()); |
+ ASSERT(use_speculative_inlining); |
+ for (intptr_t i = 0; i < inlining_black_list.length(); ++i) { |
+ ASSERT(inlining_black_list[i] != val); |
+ } |
+#endif |
+ inlining_black_list.Add(val); |
+ const intptr_t max_attempts = FLAG_max_speculative_inlining_attempts; |
+ if (inlining_black_list.length() >= max_attempts) { |
+ use_speculative_inlining = false; |
+ if (FLAG_trace_compiler) { |
+ THR_Print("Disabled speculative inlining after %" Pd " attempts.\n", |
+ inlining_black_list.length()); |
+ } |
+ } |
} else { |
// If the error isn't due to an out of range branch offset, we don't |
// try again (done = true), and indicate that we did not finish |