[turboprop] Fix an incorrect DCHECK

When setting optimized code on feedback vector we had a DCHECK that
ensured the optimization tier is kNone or it is kMidTier and we are
installing TurboFan code. While this holds usually, this fails in
few corner cases like:

1. Trigger a TF concurrent compilation
2. Create a new closure with --always-opt, which triggers a TF
concurrent compilation and installs optimized code. We set
OptimizationTier to kTopTier
3. Optimized code gets deoptimized / GC clears the optimized code, but
we haven't healed the optimized code slot / optimization tier yet.
4. Concurrent compilation finishes and tries to install optimized code
but the optimization tier is still set to kTopTier.

This cl fixes the DCHECK by actually checking we are not overwriting
valid optimized code except for tiering up.

Drive by fixes: Also print optimization tier with feedback vector and
print when marking a function for optimization with --always-opt.

Bug: v8:11101, v8:9684
Change-Id: Icad673ea01bb225f8b05e727a56f890af7e86514
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2520900
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71047}
This commit is contained in:
Mythri A 2020-11-09 12:26:13 +00:00 committed by Commit Bot
parent 233f5ac164
commit a7857d44f4
3 changed files with 17 additions and 2 deletions

View File

@ -171,6 +171,16 @@ class CompilerTracer : public AllStatic {
PrintF(scope.file(), " because --always-opt");
PrintTraceSuffix(scope);
}
static void TraceMarkForAlwaysOpt(Isolate* isolate,
Handle<JSFunction> function) {
if (!FLAG_trace_opt) return;
CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintF(scope.file(), "[marking ");
function->ShortPrint(scope.file());
PrintF(scope.file(), " for optimized recompilation because --always-opt");
PrintF(scope.file(), "]\n");
}
};
} // namespace
@ -3100,6 +3110,7 @@ void Compiler::PostInstantiation(Handle<JSFunction> function) {
if (FLAG_always_opt && shared->allows_lazy_compilation() &&
!shared->optimization_disabled() &&
!function->HasAvailableOptimizedCode()) {
CompilerTracer::TraceMarkForAlwaysOpt(isolate, function);
JSFunction::EnsureFeedbackVector(function, &is_compiled_scope);
function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
}

View File

@ -898,6 +898,7 @@ void FeedbackVector::FeedbackVectorPrint(std::ostream& os) { // NOLINT
os << "\n - no optimized code";
}
os << "\n - optimization marker: " << optimization_marker();
os << "\n - optimization tier: " << optimization_tier();
os << "\n - invocation count: " << invocation_count();
os << "\n - profiler ticks: " << profiler_ticks();

View File

@ -383,8 +383,11 @@ void FeedbackVector::SaturatingIncrementProfilerTicks() {
void FeedbackVector::SetOptimizedCode(Handle<FeedbackVector> vector,
Handle<Code> code) {
DCHECK(CodeKindIsOptimizedJSFunction(code->kind()));
DCHECK(vector->optimization_tier() == OptimizationTier::kNone ||
(vector->optimization_tier() == OptimizationTier::kMidTier &&
// We should only set optimized code only when there is no valid optimized
// code or we are tiering up.
DCHECK(!vector->has_optimized_code() ||
vector->optimized_code().marked_for_deoptimization() ||
(vector->optimized_code().kind() == CodeKind::TURBOPROP &&
code->kind() == CodeKind::TURBOFAN));
// TODO(mythria): We could see a CompileOptimized marker here either from
// tests that use %OptimizeFunctionOnNextCall or because we re-mark the