Commit 1c02987d authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[compiler] Kill the deoptimized too many times bailout

With TurboFan, there should no longer be any deopt loops (aside from
bugs). So, the "too many deopts" bailout is no longer needed, at least
in its current form.

This fixes an issue where deopt counts are leaked between native
contexts, resulting in optimization being disabled unnecessarily.

Bug: v8:6402
Change-Id: Ia06374ae6b5c2d473bcdd8eef1284bf02766c2fb
Reviewed-on: https://chromium-review.googlesource.com/588894
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46961}
parent f4b2b9be
......@@ -165,7 +165,6 @@ namespace internal {
V(kObjectNotTagged, "The object is not tagged") \
V(kOptimizationDisabled, "Optimization disabled") \
V(kOptimizationDisabledForTest, "Optimization disabled for test") \
V(kDeoptimizedTooManyTimes, "Deoptimized too many times") \
V(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister, \
"Out of virtual registers while trying to allocate temp register") \
V(kParseScopeError, "Parse/scope error") \
......
......@@ -768,14 +768,6 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
return MaybeHandle<Code>();
}
// Limit the number of times we try to optimize functions.
const int kMaxDeoptCount =
FLAG_deopt_every_n_times == 0 ? FLAG_max_deopt_count : 1000;
if (info->shared_info()->deopt_count() > kMaxDeoptCount) {
info->AbortOptimization(kDeoptimizedTooManyTimes);
return MaybeHandle<Code>();
}
TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
......@@ -1642,8 +1634,8 @@ void Compiler::PostInstantiation(Handle<JSFunction> function,
Handle<SharedFunctionInfo> shared(function->shared());
if (FLAG_always_opt && shared->allows_lazy_compilation() &&
!function->shared()->HasAsmWasmData() &&
function->shared()->is_compiled()) {
!shared->optimization_disabled() && !shared->HasAsmWasmData() &&
shared->is_compiled()) {
// TODO(mvstanton): pass pretenure flag to EnsureLiterals.
JSFunction::EnsureLiterals(function);
......
......@@ -796,11 +796,6 @@ DEFINE_BOOL(external_reference_stats, false,
"print statistics on external references used during serialization")
#endif // DEBUG
// compiler.cc
DEFINE_INT(max_deopt_count, 10,
"maximum number of deoptimizations before giving up optimization of "
"a function.")
// compilation-cache.cc
DEFINE_BOOL(compilation_cache, true, "enable compilation cache")
......
......@@ -13841,10 +13841,6 @@ void Map::StartInobjectSlackTracking() {
void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
set_ic_age(new_ic_age);
if (optimization_disabled() && deopt_count() >= FLAG_max_deopt_count) {
// Re-enable optimizations if they were disabled due to deopt_count limit.
set_optimization_disabled(false);
}
set_opt_count(0);
set_deopt_count(0);
}
......
......@@ -371,9 +371,6 @@ void SharedFunctionInfo::increment_deopt_count() {
}
}
BIT_FIELD_ACCESSORS(SharedFunctionInfo, counters, opt_reenable_tries,
SharedFunctionInfo::OptReenableTriesBits)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason, opt_count,
SharedFunctionInfo::OptCountBits)
......@@ -381,17 +378,6 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
disable_optimization_reason,
SharedFunctionInfo::DisabledOptimizationReasonBits)
void SharedFunctionInfo::TryReenableOptimization() {
int tries = opt_reenable_tries();
set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax);
// We reenable optimization whenever the number of tries is a large
// enough power of 2.
if (tries >= 16 && (((tries - 1) & tries) == 0)) {
set_optimization_disabled(false);
set_deopt_count(0);
}
}
bool SharedFunctionInfo::IsUserJavaScript() {
Object* script_obj = script();
if (script_obj->IsUndefined(GetIsolate())) return false;
......
......@@ -344,13 +344,7 @@ class SharedFunctionInfo : public HeapObject {
DECL_INT_ACCESSORS(deopt_count)
inline void increment_deopt_count();
// Number of time we tried to re-enable optimization after it
// was disabled due to high number of deoptimizations.
DECL_INT_ACCESSORS(opt_reenable_tries)
inline void TryReenableOptimization();
// Stores deopt_count, opt_reenable_tries and ic_age as bit-fields.
// Stores deopt_count and ic_age as bit-fields.
inline void set_counters(int value);
inline int counters() const;
......@@ -530,7 +524,6 @@ class SharedFunctionInfo : public HeapObject {
// Bit fields in |counters|.
#define COUNTERS_BIT_FIELDS(V, _) \
V(DeoptCountBits, int, 4, _) \
V(OptReenableTriesBits, int, 18, _) \
V(ICAgeBits, int, 8, _)
DEFINE_BIT_FIELDS(COUNTERS_BIT_FIELDS)
......
......@@ -248,15 +248,6 @@ void RuntimeProfiler::MaybeOptimizeFullCodegen(JSFunction* function,
// Do not record non-optimizable functions.
if (shared->optimization_disabled()) {
if (shared->deopt_count() >= FLAG_max_deopt_count) {
// If optimization was disabled due to many deoptimizations,
// then check if the function is hot and try to reenable optimization.
int ticks = function->feedback_vector()->profiler_ticks();
if (ticks >= kProfilerTicksBeforeReenablingOptimization) {
function->feedback_vector()->set_profiler_ticks(0);
shared->TryReenableOptimization();
}
}
return;
}
if (frame->is_optimized()) return;
......@@ -314,20 +305,7 @@ void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function,
return;
}
SharedFunctionInfo* shared = function->shared();
int ticks = function->feedback_vector()->profiler_ticks();
if (shared->optimization_disabled()) {
if (shared->deopt_count() >= FLAG_max_deopt_count) {
// If optimization was disabled due to many deoptimizations,
// then check if the function is hot and try to reenable optimization.
if (ticks >= kProfilerTicksBeforeReenablingOptimization) {
function->feedback_vector()->set_profiler_ticks(0);
shared->TryReenableOptimization();
}
}
return;
}
if (function->shared()->optimization_disabled()) return;
if (frame->is_optimized()) return;
......
......@@ -711,12 +711,11 @@ TEST(BailoutReason) {
.As<v8::Function>();
i::Handle<i::JSFunction> i_function =
i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function));
// Set a high deopt count to trigger bail out.
i_function->shared()->set_opt_count(i::FLAG_max_deopt_count + 1);
i_function->shared()->set_deopt_count(i::FLAG_max_deopt_count + 1);
USE(i_function);
CompileRun(
"%OptimizeFunctionOnNextCall(Debugger);"
"%NeverOptimizeFunction(Debugger);"
"Debugger();"
"stopProfiling()");
CHECK_EQ(1, iprofiler->GetProfilesCount());
......@@ -728,11 +727,11 @@ TEST(BailoutReason) {
// The tree should look like this:
// (root)
// ""
// kDeoptimizedTooManyTimes
// kOptimizationDisabledForTest
current = PickChild(current, "");
CHECK(const_cast<v8::CpuProfileNode*>(current));
current = PickChild(current, "Debugger");
CHECK(const_cast<v8::CpuProfileNode*>(current));
CHECK(!strcmp("Deoptimized too many times", current->GetBailoutReason()));
CHECK(!strcmp("Optimization disabled for test", current->GetBailoutReason()));
}
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --no-harmony-restrict-constructor-return --max-deopt-count 200
// Flags: --allow-natives-syntax --no-harmony-restrict-constructor-return
this.FLAG_harmony_restrict_constructor_return = false;
try {
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --harmony-restrict-constructor-return --max-deopt-count 200
// Flags: --allow-natives-syntax --harmony-restrict-constructor-return
if (this.FLAG_harmony_restrict_constructor_return === undefined)
this.FLAG_harmony_restrict_constructor_return = true;
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --no-stress-fullcodegen
function f(a, b) {
%DeoptimizeNow();
return a + b;
}
// Go through enough optimization and deoptimization cycles in order for the
// function {f} to be marked as optimization disabled.
for (var i = 0; i < 16; ++i) {
%OptimizeFunctionOnNextCall(f);
f(1, 2);
}
// Make the runtime profiler perceive {f} as hot again and then verify that we
// didn't trigger an unintentional baseline compilation.
for (var i = 0; i < 100000; ++i) {
f(1, 2);
}
assertTrue(isInterpreted(f));
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