27#ifdef V8_ENABLE_SPARKPLUG
34#define OPTIMIZATION_REASON_LIST(V) \
35 V(DoNotOptimize, "do not optimize") \
36 V(HotAndStable, "hot and stable")
39#define OPTIMIZATION_REASON_CONSTANTS(Constant, message) k##Constant,
41#undef OPTIMIZATION_REASON_CONSTANTS
45 static char const* reasons[] = {
46#define OPTIMIZATION_REASON_TEXTS(Constant, message) message,
48#undef OPTIMIZATION_REASON_TEXTS
50 size_t const index =
static_cast<size_t>(reason);
52 return reasons[
index];
55#undef OPTIMIZATION_REASON_LIST
65 return {OptimizationReason::kHotAndStable, CodeKind::MAGLEV,
69 return {OptimizationReason::kHotAndStable, CodeKind::TURBOFAN_JS,
73 return {OptimizationReason::kDoNotOptimize,
96static_assert(
sizeof(OptimizationDecision) <=
kInt32Size);
103 PrintF(
"[not marking function %s (%s) for optimization: already queued]\n",
104 function->DebugNameCStr().get(),
112 "[not marking function %s for optimization: marked with "
113 "%%PrepareFunctionForOptimization for manual optimization]\n",
114 function->DebugNameCStr().get());
119 OptimizationDecision d) {
121 CodeTracer::Scope scope(isolate->GetCodeTracer());
122 PrintF(scope.file(),
"[marking ");
124 PrintF(scope.file(),
" for optimization to %s, %s, reason: %s",
127 PrintF(scope.file(),
"]\n");
136 PrintF(
"[manually marking ");
145 DCHECK(d.should_optimize());
146 TraceRecompile(
isolate_, function, d);
147 function->RequestOptimization(
isolate_, d.code_kind, d.concurrency_mode);
159 return !function->has_feedback_vector() ||
165 (function->ActiveTierIsIgnition(isolate) &&
167 function->shared()->cached_tiering_decision() ==
171bool TiersUpToMaglev(
CodeKind code_kind) {
176bool TiersUpToMaglev(std::optional<CodeKind> code_kind) {
177 return code_kind.has_value() && TiersUpToMaglev(code_kind.value());
180int InterruptBudgetFor(Isolate* isolate, std::optional<CodeKind> code_kind,
183 int bytecode_length) {
185 if (function->tiering_in_progress())
return INT_MAX / 2;
187 const std::optional<CodeKind> existing_request =
188 function->GetRequestedOptimizationIfAny(isolate);
189 if (existing_request == CodeKind::TURBOFAN_JS ||
190 (code_kind.has_value() && code_kind.value() == CodeKind::TURBOFAN_JS)) {
191 return v8_flags.invocation_count_for_osr * bytecode_length;
194 return v8_flags.invocation_count_for_maglev_osr * bytecode_length;
197 if (TiersUpToMaglev(code_kind) &&
198 !function->IsTieringRequestedOrInProgress()) {
199 if (
v8_flags.profile_guided_optimization) {
200 switch (cached_tiering_decision) {
202 return (std::max(
v8_flags.invocation_count_for_maglev,
203 v8_flags.minimum_invocations_after_ic_update) +
204 v8_flags.invocation_count_for_maglev_with_delay) *
208 return v8_flags.invocation_count_for_early_optimization *
213 return v8_flags.invocation_count_for_maglev * bytecode_length;
220 return v8_flags.invocation_count_for_maglev * bytecode_length;
222 return v8_flags.invocation_count_for_turbofan * bytecode_length;
230 std::optional<CodeKind> override_active_tier) {
231 DCHECK(function->shared()->is_compiled());
232 const int bytecode_length =
233 function->shared()->GetBytecodeArray(isolate)->length();
235 if (FirstTimeTierUpToSparkplug(isolate, function)) {
236 return bytecode_length *
v8_flags.invocation_count_for_feedback_allocation;
239 DCHECK(function->has_feedback_vector());
240 if (bytecode_length >
v8_flags.max_optimized_bytecode_size) {
246 return ::i::InterruptBudgetFor(
248 override_active_tier ? override_active_tier
249 : function->GetActiveTier(isolate),
250 function, function->shared()->cached_tiering_decision(), bytecode_length);
259 if (
V8_UNLIKELY(shared->optimization_disabled()))
return;
267 "[OSR - setting osr urgency. function: %s, old urgency: %d, new "
269 function->DebugNameCStr().get(), fv->osr_urgency(), osr_urgency);
272 DCHECK_GE(osr_urgency, fv->osr_urgency());
273 fv->set_osr_urgency(osr_urgency);
277 int old_urgency = function->feedback_vector()->osr_urgency();
279 TrySetOsrUrgency(isolate, function, new_urgency);
282void TryRequestOsrAtNextOpportunity(Isolate* isolate,
291 TryRequestOsrAtNextOpportunity(
isolate_, function);
296 const bool tiering_in_progress = function->tiering_in_progress();
297 const bool osr_in_progress =
298 function->feedback_vector()->osr_tiering_in_progress();
302 if (
v8_flags.concurrent_recompilation_front_running &&
303 ((tiering_in_progress && function->ActiveTierIsMaglev(
isolate_)) ||
305 function->feedback_vector()->maybe_has_optimized_osr_code()))) {
314 TraceInOptimizationQueue(function, current_code_kind);
321 TraceHeuristicOptimizationDisallowed(function);
326 if (
V8_UNLIKELY(function->shared()->optimization_disabled()))
return;
329 TryRequestOsrAtNextOpportunity(
isolate_, function);
335 const bool waiting_for_tierup =
336 (current_code_kind < CodeKind::TURBOFAN_JS &&
337 (available_kinds & CodeKindFlag::TURBOFAN_JS)) ||
338 (maglev_osr && current_code_kind < CodeKind::MAGLEV &&
339 (available_kinds & CodeKindFlag::MAGLEV));
342 if (function->IsOptimizationRequested(
isolate_) || waiting_for_tierup) {
343 if (
V8_UNLIKELY(maglev_osr && current_code_kind == CodeKind::MAGLEV &&
352 TryIncrementOsrUrgency(
isolate_, function);
359 const std::optional<CodeKind> existing_request =
360 function->GetRequestedOptimizationIfAny(
isolate_);
361 DCHECK(existing_request != CodeKind::TURBOFAN_JS);
362 DCHECK(!function->HasAvailableCodeKind(
isolate_, CodeKind::TURBOFAN_JS));
369 d.should_optimize() && d.code_kind == CodeKind::MAGLEV)) {
370 bool is_marked_for_maglev_optimization =
371 existing_request == CodeKind::MAGLEV ||
372 (available_kinds & CodeKindFlag::MAGLEV);
373 if (is_marked_for_maglev_optimization) {
374 d =
ShouldOptimize(function->feedback_vector(), CodeKind::MAGLEV);
379 d.code_kind != CodeKind::TURBOFAN_JS)) {
383 if (d.should_optimize())
Optimize(function, d);
389 if (current_code_kind == CodeKind::TURBOFAN_JS) {
393 if (TiersUpToMaglev(current_code_kind) &&
394 shared->PassesFilter(
v8_flags.maglev_filter) &&
395 !shared->maglev_compilation_failed()) {
396 if (
v8_flags.profile_guided_optimization &&
397 shared->cached_tiering_decision() ==
405 !shared->PassesFilter(
v8_flags.turbo_filter) ||
406 (
v8_flags.efficiency_mode_disable_turbofan &&
413 v8_flags.efficiency_mode_delay_turbofan &&
414 feedback_vector->invocation_count() <
415 v8_flags.efficiency_mode_delay_turbofan) {
420 if (bytecode->length() >
v8_flags.max_optimized_bytecode_size) {
429bool ShouldResetInterruptBudgetByICChange(
431 switch (cached_tiering_decision) {
449 CodeKind code_kind = vector->shared_function_info()->HasBaselineCode()
451 : CodeKind::INTERPRETED_FUNCTION;
453#ifndef V8_ENABLE_LEAPTIERING
454 if (vector->has_optimized_code()) {
455 code_kind = vector->optimized_code(
isolate_)->kind();
459 if (code_kind == CodeKind::INTERPRETED_FUNCTION &&
461 vector->shared_function_info()->cached_tiering_decision() ==
471 int bytecode_length = shared->GetBytecodeArray(
isolate_)->length();
473 int invocations =
v8_flags.minimum_invocations_after_ic_update;
474 int bytecodes = std::min(bytecode_length, (
kMaxInt >> 1) / invocations);
475 int new_budget = invocations * bytecodes;
476 int current_budget = cell->interrupt_budget();
477 if (
v8_flags.profile_guided_optimization &&
478 shared->cached_tiering_decision() <=
482 if (vector->invocation_count_before_stable() <
483 v8_flags.invocation_count_for_early_optimization) {
486 int new_invocation_count_before_stable;
487 if (vector->interrupt_budget_reset_by_ic_change()) {
490 int new_consumed_budget = new_budget - current_budget;
491 new_invocation_count_before_stable =
493 std::ceil(
static_cast<float>(new_consumed_budget) / bytecodes);
497 int total_consumed_budget =
499 ?
v8_flags.invocation_count_for_maglev
500 :
v8_flags.invocation_count_for_turbofan) *
503 new_invocation_count_before_stable =
504 std::ceil(
static_cast<float>(total_consumed_budget) / bytecodes);
506 if (new_invocation_count_before_stable >=
507 v8_flags.invocation_count_for_early_optimization) {
508 vector->set_invocation_count_before_stable(
512 vector->set_invocation_count_before_stable(
519 if (!
v8_flags.profile_guided_optimization ||
520 ShouldResetInterruptBudgetByICChange(
521 shared->cached_tiering_decision())) {
522 if (new_budget > current_budget) {
524 PrintF(
"[delaying optimization of %s, IC changed]\n",
525 shared->DebugNameCStr().get());
527 vector->set_interrupt_budget_reset_by_ic_change(
true);
528 cell->set_interrupt_budget(new_budget);
536 "V8.MarkCandidatesForOptimization");
542 function->shared()->is_compiled_scope(
isolate_));
548 const bool had_feedback_vector = function->has_feedback_vector();
549 const bool first_time_tiered_up_to_sparkplug =
550 FirstTimeTierUpToSparkplug(
isolate_, *function);
553 const bool maybe_had_optimized_osr_code =
554 had_feedback_vector &&
555 function->feedback_vector()->maybe_has_optimized_osr_code();
556 const bool compile_sparkplug =
558 function->ActiveTierIsIgnition(
isolate_) && !maybe_had_optimized_osr_code;
561 if (!had_feedback_vector) {
562 if (compile_sparkplug && function->shared()->cached_tiering_decision() ==
567 function->shared()->set_cached_tiering_decision(
576 function->feedback_vector()->set_invocation_count(1,
kRelaxedStore);
579 DCHECK(function->has_feedback_vector());
580 DCHECK(function->shared()->is_compiled());
581 DCHECK(function->shared()->HasBytecodeArray());
591 if (compile_sparkplug) {
592#ifdef V8_ENABLE_SPARKPLUG
593 if (
v8_flags.baseline_batch_compilation) {
594 isolate_->baseline_batch_compiler()->EnqueueFunction(function);
597 function->shared()->is_compiled_scope(
isolate_));
599 &inner_is_compiled_scope);
607 if (first_time_tiered_up_to_sparkplug) {
611 if (had_feedback_vector) {
612 if (function->shared()->cached_tiering_decision() ==
614 function->shared()->set_cached_tiering_decision(
639 DCHECK(had_feedback_vector);
#define SBXCHECK(condition)
static bool CompileBaseline(Isolate *isolate, DirectHandle< JSFunction > function, ClearExceptionFlag flag, IsCompiledScope *is_compiled_scope)
static constexpr uint8_t kInvocationCountBeforeStableDeoptSentinel
static constexpr int kMaxOsrUrgency
bool EfficiencyModeEnabledForTiering()
void IncreaseConcurrentOptimizationPriority(CodeKind kind, Tagged< SharedFunctionInfo > function)
bool BatterySaverModeEnabled()
static void CreateAndAttachFeedbackVector(Isolate *isolate, DirectHandle< JSFunction > function, IsCompiledScope *compiled_scope)
static bool IsMarkedForManualOptimization(Isolate *isolate, Tagged< JSFunction > function)
OptimizationDecision()=default
static constexpr OptimizationDecision Maglev()
constexpr bool should_optimize() const
OptimizationReason optimization_reason
static constexpr OptimizationDecision DoNotOptimize()
static constexpr OptimizationDecision TurbofanHotAndStable()
constexpr OptimizationDecision(OptimizationReason optimization_reason, CodeKind code_kind, ConcurrencyMode concurrency_mode)
ConcurrencyMode concurrency_mode
void RequestOsrAtNextOpportunity(Tagged< JSFunction > function)
void MaybeOptimizeFrame(Tagged< JSFunction > function, CodeKind code_kind)
OptimizationDecision ShouldOptimize(Tagged< FeedbackVector > feedback_vector, CodeKind code_kind)
void NotifyICChanged(Tagged< FeedbackVector > vector)
static int InterruptBudgetFor(Isolate *isolate, Tagged< JSFunction > function, std::optional< CodeKind > override_active_tier={})
void Optimize(Tagged< JSFunction > function, OptimizationDecision decision)
void OnInterruptTick(DirectHandle< JSFunction > function, CodeKind code_kind)
void MarkForTurboFanOptimization(Tagged< JSFunction > function)
static bool IsMaglevOsrEnabled()
static bool IsMaglevEnabled()
constexpr const char * ToString(DeoptimizeKind kind)
void PrintF(const char *format,...)
const char * CodeKindToString(CodeKind kind)
char const * OptimizationReasonToString(OptimizationReason reason)
Tagged(T object) -> Tagged< T >
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
OPTIMIZATION_REASON_CONSTANTS(Constant, message)
void ShortPrint(Tagged< Object > obj, FILE *out)
void TraceManualRecompile(Tagged< JSFunction > function, CodeKind code_kind, ConcurrencyMode concurrency_mode)
constexpr bool CodeKindIsUnoptimizedJSFunction(CodeKind kind)
V8_EXPORT_PRIVATE FlagValues v8_flags
static constexpr bool kTieringStateInProgressBlocksTierup
bool CanCompileWithBaseline(Isolate *isolate, Tagged< SharedFunctionInfo > shared)
static constexpr RelaxedLoadTag kRelaxedLoad
static constexpr RelaxedStoreTag kRelaxedStore
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define OPTIMIZATION_REASON_LIST(V)
#define OPTIMIZATION_REASON_TEXTS(Constant, message)
#define TRACE_EVENT0(category_group, name)
#define TRACE_DISABLED_BY_DEFAULT(name)
#define V8_LIKELY(condition)
#define V8_UNLIKELY(condition)