Commit 0d01850e authored by Mythri A's avatar Mythri A Committed by Commit Bot

[turboprop] Reuse deoptimized code for specified number of soft deopts

We give the optimized code another chance on soft deopts in TurboProp.
If the deopt is happening on infrequently taken paths, then this will
let us reuse the optimized code for the subsequent executions. If the
soft deopts are happening multiple times on the same code, then we would
discard the optimized code. The number of deopts we would wait is
controlled by FLAG_reuse_opt_code_count.

BUG=v8:10433

Change-Id: Iaadea4cffde7d7d55be4875c9586694dca64957c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2093503
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67289}
parent c66f220a
......@@ -498,6 +498,7 @@ DEFINE_BOOL(turboprop, false,
DEFINE_NEG_IMPLICATION(turboprop, turbo_inlining)
DEFINE_IMPLICATION(turboprop, concurrent_inlining)
DEFINE_VALUE_IMPLICATION(turboprop, interrupt_budget, 15 * KB)
DEFINE_VALUE_IMPLICATION(turboprop, reuse_opt_code_count, 2)
// Flags for concurrent recompilation.
DEFINE_BOOL(concurrent_recompilation, true,
......@@ -648,6 +649,8 @@ DEFINE_BOOL(
stress_gc_during_compilation, false,
"simulate GC/compiler thread race related to https://crbug.com/v8/8520")
DEFINE_BOOL(turbo_fast_api_calls, false, "enable fast API calls from TurboFan")
DEFINE_INT(reuse_opt_code_count, 0,
"don't discard optimized code for the specified number of deopts.")
// Favor memory over execution speed.
DEFINE_BOOL(optimize_for_size, false,
......
......@@ -488,6 +488,24 @@ void Code::set_marked_for_deoptimization(bool flag) {
code_data_container().set_kind_specific_flags(updated);
}
int Code::deoptimization_count() const {
DCHECK(kind() == OPTIMIZED_FUNCTION);
int32_t flags = code_data_container().kind_specific_flags();
int count = DeoptCountField::decode(flags);
DCHECK_GE(count, 0);
return count;
}
void Code::increment_deoptimization_count() {
DCHECK(kind() == OPTIMIZED_FUNCTION);
int32_t flags = code_data_container().kind_specific_flags();
int32_t count = DeoptCountField::decode(flags);
DCHECK_GE(count, 0);
CHECK_LE(count + 1, DeoptCountField::kMax);
int32_t updated = DeoptCountField::update(flags, count + 1);
code_data_container().set_kind_specific_flags(updated);
}
bool Code::embedded_objects_cleared() const {
DCHECK(kind() == OPTIMIZED_FUNCTION);
int32_t flags = code_data_container().kind_specific_flags();
......
......@@ -183,6 +183,12 @@ class Code : public HeapObject {
inline bool marked_for_deoptimization() const;
inline void set_marked_for_deoptimization(bool flag);
// [deoptimzation_count]: In turboprop we retain the deoptimized code on soft
// deopts for a certain number of soft deopts. This field keeps track of
// number of deoptimizations we have seen so far.
inline int deoptimization_count() const;
inline void increment_deoptimization_count();
// [embedded_objects_cleared]: For kind OPTIMIZED_FUNCTION tells whether
// the embedded objects in the code marked for deoptimization were cleared.
// Note that embedded_objects_cleared() implies marked_for_deoptimization().
......@@ -458,11 +464,11 @@ class Code : public HeapObject {
V(DeoptAlreadyCountedField, bool, 1, _) \
V(CanHaveWeakObjectsField, bool, 1, _) \
V(IsPromiseRejectionField, bool, 1, _) \
V(IsExceptionCaughtField, bool, 1, _)
V(IsExceptionCaughtField, bool, 1, _) \
V(DeoptCountField, int, 4, _)
DEFINE_BIT_FIELDS(CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS)
#undef CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS
static_assert(IsExceptionCaughtField::kLastUsedBit < 32,
"KindSpecificFlags full");
static_assert(DeoptCountField::kLastUsedBit < 32, "KindSpecificFlags full");
// The {marked_for_deoptimization} field is accessed from generated code.
static const int kMarkedForDeoptimizationBit =
......
......@@ -171,6 +171,12 @@ RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
JavaScriptFrame* top_frame = top_it.frame();
isolate->set_context(Context::cast(top_frame->context()));
int count = optimized_code->deoptimization_count();
if (type == DeoptimizeKind::kSoft && count < FLAG_reuse_opt_code_count) {
optimized_code->increment_deoptimization_count();
return ReadOnlyRoots(isolate).undefined_value();
}
// Invalidate the underlying optimized code on non-lazy deopts.
if (type != DeoptimizeKind::kLazy) {
Deoptimizer::DeoptimizeFunction(*function, *optimized_code);
......
......@@ -1151,6 +1151,12 @@
# interrupt_budget overrides don't work with TurboProp.
'interrupt-budget-override': [SKIP],
'never-optimize': [SKIP],
# In turboprop we reuse the optimized code on soft deopt. The following tests
# test for a soft deopt and they won't work in TurboProp.
'deopt-recursive-soft-once': [SKIP],
'regress/regress-3709': [SKIP],
'regress/regress-5790': [SKIP],
}], # variant == turboprop
##############################################################################
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment