diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc index 5975c37d064..aabdc136de1 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc @@ -249,8 +249,8 @@ void FlowGraphCompiler::InitCompiler() { } } -bool FlowGraphCompiler::CanOptimize() { - return FLAG_optimization_counter_threshold >= 0; +bool FlowGraphCompiler::CanOptimize() const { + return thread()->isolate_group()->optimization_counter_threshold() >= 0; } bool FlowGraphCompiler::CanOptimizeFunction() const { @@ -2207,16 +2207,16 @@ intptr_t FlowGraphCompiler::GetOptimizationThreshold() const { threshold = FLAG_reoptimization_counter_threshold; } else if (parsed_function_.function().IsIrregexpFunction()) { threshold = FLAG_regexp_optimization_counter_threshold; - } else if (FLAG_randomize_optimization_counter) { - threshold = Thread::Current()->random()->NextUInt64() % - FLAG_optimization_counter_threshold; } else { + const auto configured_optimization_counter_threshold = + IsolateGroup::Current()->optimization_counter_threshold(); + const intptr_t basic_blocks = flow_graph().preorder().length(); ASSERT(basic_blocks > 0); threshold = FLAG_optimization_counter_scale * basic_blocks + FLAG_min_optimization_counter_threshold; - if (threshold > FLAG_optimization_counter_threshold) { - threshold = FLAG_optimization_counter_threshold; + if (threshold > configured_optimization_counter_threshold) { + threshold = configured_optimization_counter_threshold; } } diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h index 44f16a0b020..aff71c485be 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.h +++ b/runtime/vm/compiler/backend/flow_graph_compiler.h @@ -509,7 +509,7 @@ class FlowGraphCompiler : public ValueObject { Instruction* current_instruction() const { return current_instruction_; } - static bool CanOptimize(); + bool CanOptimize() const; bool CanOptimizeFunction() const; bool CanOSRFunction() const; bool is_optimizing() const { return is_optimizing_; } diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 950b06c3be0..4453779fd87 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -705,18 +705,18 @@ Cids* Cids::CreateForArgument(Zone* zone, return cids; } -static intptr_t Usage(const Function& function) { +static intptr_t Usage(Thread* thread, const Function& function) { intptr_t count = function.usage_counter(); if (count < 0) { if (function.HasCode()) { // 'function' is queued for optimized compilation - count = FLAG_optimization_counter_threshold; + count = thread->isolate_group()->optimization_counter_threshold(); } else { count = 0; } } else if (Code::IsOptimized(function.CurrentCode())) { // 'function' was optimized and stopped counting - count = FLAG_optimization_counter_threshold; + count = thread->isolate_group()->optimization_counter_threshold(); } return count; } @@ -770,7 +770,7 @@ void CallTargets::CreateHelper(Zone* zone, const ICData& ic_data) { const intptr_t filled_entry_count = cache.filled_entry_count(); ASSERT(filled_entry_count > 0); cid_ranges_.Add(new (zone) TargetInfo( - id, id, &function, Usage(function) / filled_entry_count, + id, id, &function, Usage(thread, function) / filled_entry_count, StaticTypeExactnessState::NotTracking())); } } diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index e648aa351c8..4fe75bfc2e6 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -3300,8 +3300,10 @@ void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // stack checks. Use progressively higher thresholds for more deeply // nested loops to attempt to hit outer loops with OSR when possible. __ LoadObject(function, compiler->parsed_function().function()); - intptr_t threshold = - FLAG_optimization_counter_threshold * (loop_depth() + 1); + const intptr_t configured_optimization_counter_threshold = + compiler->thread()->isolate_group()->optimization_counter_threshold(); + const int32_t threshold = + configured_optimization_counter_threshold * (loop_depth() + 1); __ ldr(count, compiler::FieldAddress( function, compiler::target::Function::usage_counter_offset())); diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index d889d705cd2..91f1d67fec5 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -2935,8 +2935,10 @@ void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // stack checks. Use progressively higher thresholds for more deeply // nested loops to attempt to hit outer loops with OSR when possible. __ LoadObject(function, compiler->parsed_function().function()); - intptr_t threshold = - FLAG_optimization_counter_threshold * (loop_depth() + 1); + const intptr_t configured_optimization_counter_threshold = + compiler->thread()->isolate_group()->optimization_counter_threshold(); + const int32_t threshold = + configured_optimization_counter_threshold * (loop_depth() + 1); __ LoadFieldFromOffset(TMP, function, Function::usage_counter_offset(), compiler::kFourBytes); __ add(TMP, TMP, compiler::Operand(1)); diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc index 285c72821cf..623d36fcd22 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -2548,8 +2548,10 @@ void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // stack checks. Use progressively higher thresholds for more deeply // nested loops to attempt to hit outer loops with OSR when possible. __ LoadObject(EDI, compiler->parsed_function().function()); - intptr_t threshold = - FLAG_optimization_counter_threshold * (loop_depth() + 1); + const intptr_t configured_optimization_counter_threshold = + compiler->thread()->isolate_group()->optimization_counter_threshold(); + const int32_t threshold = + configured_optimization_counter_threshold * (loop_depth() + 1); __ incl(compiler::FieldAddress(EDI, Function::usage_counter_offset())); __ cmpl(compiler::FieldAddress(EDI, Function::usage_counter_offset()), compiler::Immediate(threshold)); diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc index 6c15a7eaea4..60bdf3c3e37 100644 --- a/runtime/vm/compiler/backend/il_riscv.cc +++ b/runtime/vm/compiler/backend/il_riscv.cc @@ -3282,8 +3282,10 @@ void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // stack checks. Use progressively higher thresholds for more deeply // nested loops to attempt to hit outer loops with OSR when possible. __ LoadObject(function, compiler->parsed_function().function()); - intptr_t threshold = - FLAG_optimization_counter_threshold * (loop_depth() + 1); + const intptr_t configured_optimization_counter_threshold = + compiler->thread()->isolate_group()->optimization_counter_threshold(); + const int32_t threshold = + configured_optimization_counter_threshold * (loop_depth() + 1); __ LoadFieldFromOffset(TMP, function, Function::usage_counter_offset(), compiler::kFourBytes); __ addi(TMP, TMP, 1); diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index 6c79490dc10..54198e9adb4 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -2952,8 +2952,10 @@ void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // stack checks. Use progressively higher thresholds for more deeply // nested loops to attempt to hit outer loops with OSR when possible. __ LoadObject(temp, compiler->parsed_function().function()); - int32_t threshold = - FLAG_optimization_counter_threshold * (loop_depth() + 1); + const intptr_t configured_optimization_counter_threshold = + compiler->thread()->isolate_group()->optimization_counter_threshold(); + const int32_t threshold = + configured_optimization_counter_threshold * (loop_depth() + 1); __ incl(compiler::FieldAddress(temp, Function::usage_counter_offset())); __ cmpl(compiler::FieldAddress(temp, Function::usage_counter_offset()), compiler::Immediate(threshold)); diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc index bcfe3c90e5e..bfcc52cc1e5 100644 --- a/runtime/vm/compiler/jit/compiler.cc +++ b/runtime/vm/compiler/jit/compiler.cc @@ -234,7 +234,7 @@ bool Compiler::CanOptimizeFunction(Thread* thread, const Function& function) { // immediately, causing an infinite compilation loop. The compiler raises // the threshold for functions with breakpoints, so we drop the unoptimized // to force it to be recompiled. - if (CanOptimizeImmediately()) { + if (thread->isolate_group()->optimization_counter_threshold() < 2) { function.ClearCode(); } return false; @@ -433,7 +433,8 @@ CodePtr CompileParsedFunctionHelper::FinalizeCompilation( function.SetUsageCounter(0); } else { // Trigger another optimization pass soon. - function.SetUsageCounter(FLAG_optimization_counter_threshold - 100); + function.SetUsageCounter( + thread()->isolate_group()->optimization_counter_threshold() - 100); } } @@ -732,7 +733,8 @@ static ObjectPtr CompileFunctionHelper(CompilationPipeline* pipeline, } // Trigger another optimization pass soon. - function.SetUsageCounter(FLAG_optimization_counter_threshold - 100); + function.SetUsageCounter( + thread->isolate_group()->optimization_counter_threshold() - 100); return Error::null(); } else if (error.IsLanguageError() && LanguageError::Cast(error).kind() == Report::kBailout) { diff --git a/runtime/vm/compiler/jit/compiler.h b/runtime/vm/compiler/jit/compiler.h index 36966c9a7bf..f2e3e44ce33 100644 --- a/runtime/vm/compiler/jit/compiler.h +++ b/runtime/vm/compiler/jit/compiler.h @@ -76,15 +76,6 @@ class Compiler : public AllStatic { // The result for a function may change if debugging gets turned on/off. static bool CanOptimizeFunction(Thread* thread, const Function& function); -#if !defined(PRODUCT) - // Whether it's possible for unoptimized code to optimize immediately on entry - // (can happen with random or very low optimization counter thresholds) - static bool CanOptimizeImmediately() { - return FLAG_optimization_counter_threshold < 2 || - FLAG_randomize_optimization_counter; - } -#endif - // Generates code for given function without optimization and sets its code // field. // diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h index 964c4c54ae1..2f448049ef0 100644 --- a/runtime/vm/flag_list.h +++ b/runtime/vm/flag_list.h @@ -27,6 +27,8 @@ constexpr bool kDartUseBackgroundCompilation = false; constexpr bool kDartUseBackgroundCompilation = true; #endif +constexpr intptr_t kDefaultOptimizationCounterThreshold = 30000; + // The disassembler might be force included even in product builds so we need // to conditionally make these into product flags to make the disassembler // usable in product mode. @@ -156,11 +158,8 @@ constexpr bool FLAG_support_il_printer = false; "Max size of new gen semi space in MB") \ P(new_gen_semi_initial_size, int, (kWordSize <= 4) ? 1 : 2, \ "Initial size of new gen semi space in MB") \ - P(optimization_counter_threshold, int, 30000, \ + P(optimization_counter_threshold, int, kDefaultOptimizationCounterThreshold, \ "Function's usage-counter value before it is optimized, -1 means never") \ - R(randomize_optimization_counter, false, bool, false, \ - "Randomize optimization counter thresholds on a per-function basis (for " \ - "testing).") \ P(optimization_level, int, 2, \ "Optimization level: 1 (favor size), 2 (default), 3 (favor speed)") \ P(old_gen_heap_size, int, kDefaultMaxOldGenHeapSize, \ diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index 5b19f0bea1e..05266a68b1e 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -324,6 +324,14 @@ class IsolateGroup : public IntrusiveDListEntry { return background_compiler_.get(); #endif } +#if !defined(DART_PRECOMPILED_RUNTIME) + intptr_t optimization_counter_threshold() const { + if (IsSystemIsolateGroup(this)) { + return kDefaultOptimizationCounterThreshold; + } + return FLAG_optimization_counter_threshold; + } +#endif #if !defined(PRODUCT) GroupDebugger* debugger() const { return debugger_; }