Commit 75c5d82b authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[compiler] Spawn concurrent jobs for --stress-concurrent-inlining

.. to increase coverage of concurrent inlining, at least in this stress
mode. The common pattern in mjsunit tests is to call
`%OptimizeFunctionOnNextCall(f)` for interesting function `f`. This
explicitly triggers non-concurrent compilation, significantly decreasing
relevant coverage of concurrent inlining.

This CL recovers coverage by spawning an additional concurrent compile
job when 1. --stress-concurrent-inlining is enabled, and 2. the
requested compile mode is non-concurrent. The result of these
additional jobs is discarded.

Drive-by: Fix two simple uncovered issues.

Bug: v8:7790,v8:11513,v8:11648
Change-Id: If1e8ca5ba737e3cecdec9e15e4a86b28fe9fb2de
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2824440
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73967}
parent 5c210efe
...@@ -1177,10 +1177,19 @@ Handle<Code> ContinuationForConcurrentOptimization( ...@@ -1177,10 +1177,19 @@ Handle<Code> ContinuationForConcurrentOptimization(
return BUILTIN_CODE(isolate, InterpreterEntryTrampoline); return BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
} }
enum class GetOptimizedCodeResultHandling {
// Default behavior, i.e. install the result, insert into caches, etc.
kDefault,
// Used only for stress testing. The compilation result should be discarded.
kDiscardForTesting,
};
MaybeHandle<Code> GetOptimizedCode( MaybeHandle<Code> GetOptimizedCode(
Handle<JSFunction> function, ConcurrencyMode mode, CodeKind code_kind, Handle<JSFunction> function, ConcurrencyMode mode, CodeKind code_kind,
BytecodeOffset osr_offset = BytecodeOffset::None(), BytecodeOffset osr_offset = BytecodeOffset::None(),
JavaScriptFrame* osr_frame = nullptr) { JavaScriptFrame* osr_frame = nullptr,
GetOptimizedCodeResultHandling result_handling =
GetOptimizedCodeResultHandling::kDefault) {
DCHECK(CodeKindIsOptimizedJSFunction(code_kind)); DCHECK(CodeKindIsOptimizedJSFunction(code_kind));
Isolate* isolate = function->GetIsolate(); Isolate* isolate = function->GetIsolate();
...@@ -1262,6 +1271,10 @@ MaybeHandle<Code> GetOptimizedCode( ...@@ -1262,6 +1271,10 @@ MaybeHandle<Code> GetOptimizedCode(
has_script, osr_offset, osr_frame)); has_script, osr_offset, osr_frame));
OptimizedCompilationInfo* compilation_info = job->compilation_info(); OptimizedCompilationInfo* compilation_info = job->compilation_info();
if (result_handling == GetOptimizedCodeResultHandling::kDiscardForTesting) {
compilation_info->set_discard_result_for_testing();
}
// Prepare the job and launch concurrent compilation, or compile now. // Prepare the job and launch concurrent compilation, or compile now.
if (mode == ConcurrencyMode::kConcurrent) { if (mode == ConcurrencyMode::kConcurrent) {
if (GetOptimizedCodeLater(std::move(job), isolate, compilation_info, if (GetOptimizedCodeLater(std::move(job), isolate, compilation_info,
...@@ -1280,6 +1293,20 @@ MaybeHandle<Code> GetOptimizedCode( ...@@ -1280,6 +1293,20 @@ MaybeHandle<Code> GetOptimizedCode(
return {}; return {};
} }
// When --stress-concurrent-inlining is enabled, spawn concurrent jobs in
// addition to non-concurrent compiles to increase coverage in mjsunit tests
// (where most interesting compiles are non-concurrent). The result of the
// compilation is thrown out.
void SpawnDuplicateConcurrentJobForStressTesting(Handle<JSFunction> function,
ConcurrencyMode mode,
CodeKind code_kind) {
DCHECK(FLAG_stress_concurrent_inlining && FLAG_concurrent_recompilation &&
mode == ConcurrencyMode::kNotConcurrent);
USE(GetOptimizedCode(function, ConcurrencyMode::kConcurrent, code_kind,
BytecodeOffset::None(), nullptr,
GetOptimizedCodeResultHandling::kDiscardForTesting));
}
bool FailAndClearPendingException(Isolate* isolate) { bool FailAndClearPendingException(Isolate* isolate) {
isolate->clear_pending_exception(); isolate->clear_pending_exception();
return false; return false;
...@@ -1552,6 +1579,7 @@ void CompileOnBackgroundThread(ParseInfo* parse_info, ...@@ -1552,6 +1579,7 @@ void CompileOnBackgroundThread(ParseInfo* parse_info,
// Character stream shouldn't be used again. // Character stream shouldn't be used again.
parse_info->ResetCharacterStream(); parse_info->ResetCharacterStream();
} }
} // namespace } // namespace
CompilationHandleScope::~CompilationHandleScope() { CompilationHandleScope::~CompilationHandleScope() {
...@@ -1992,9 +2020,17 @@ bool Compiler::Compile(Isolate* isolate, Handle<JSFunction> function, ...@@ -1992,9 +2020,17 @@ bool Compiler::Compile(Isolate* isolate, Handle<JSFunction> function,
CompilerTracer::TraceOptimizeForAlwaysOpt(isolate, function, CompilerTracer::TraceOptimizeForAlwaysOpt(isolate, function,
CodeKindForTopTier()); CodeKindForTopTier());
const CodeKind code_kind = CodeKindForTopTier();
const ConcurrencyMode concurrency_mode = ConcurrencyMode::kNotConcurrent;
if (FLAG_stress_concurrent_inlining && FLAG_concurrent_recompilation &&
concurrency_mode == ConcurrencyMode::kNotConcurrent) {
SpawnDuplicateConcurrentJobForStressTesting(function, concurrency_mode,
code_kind);
}
Handle<Code> maybe_code; Handle<Code> maybe_code;
if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent, if (GetOptimizedCode(function, concurrency_mode, code_kind)
CodeKindForTopTier())
.ToHandle(&maybe_code)) { .ToHandle(&maybe_code)) {
code = maybe_code; code = maybe_code;
} }
...@@ -2091,6 +2127,11 @@ bool Compiler::CompileOptimized(Isolate* isolate, Handle<JSFunction> function, ...@@ -2091,6 +2127,11 @@ bool Compiler::CompileOptimized(Isolate* isolate, Handle<JSFunction> function,
DCHECK(CodeKindIsOptimizedJSFunction(code_kind)); DCHECK(CodeKindIsOptimizedJSFunction(code_kind));
DCHECK(AllowCompilation::IsAllowed(isolate)); DCHECK(AllowCompilation::IsAllowed(isolate));
if (FLAG_stress_concurrent_inlining && FLAG_concurrent_recompilation &&
mode == ConcurrencyMode::kNotConcurrent) {
SpawnDuplicateConcurrentJobForStressTesting(function, mode, code_kind);
}
Handle<Code> code; Handle<Code> code;
if (!GetOptimizedCode(function, mode, code_kind).ToHandle(&code)) { if (!GetOptimizedCode(function, mode, code_kind).ToHandle(&code)) {
// Optimization failed, get the existing code. We could have optimized code // Optimization failed, get the existing code. We could have optimized code
...@@ -3226,9 +3267,10 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job, ...@@ -3226,9 +3267,10 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
Handle<SharedFunctionInfo> shared = compilation_info->shared_info(); Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
CodeKind code_kind = compilation_info->code_kind(); CodeKind code_kind = compilation_info->code_kind();
const bool use_result = !compilation_info->discard_result_for_testing();
const bool should_install_code_on_function = const bool should_install_code_on_function =
!CodeKindIsNativeContextIndependentJSFunction(code_kind); !CodeKindIsNativeContextIndependentJSFunction(code_kind);
if (should_install_code_on_function) { if (V8_LIKELY(should_install_code_on_function && use_result)) {
// Reset profiler ticks, function is no longer considered hot. // Reset profiler ticks, function is no longer considered hot.
compilation_info->closure()->feedback_vector().set_profiler_ticks(0); compilation_info->closure()->feedback_vector().set_profiler_ticks(0);
} }
...@@ -3248,12 +3290,14 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job, ...@@ -3248,12 +3290,14 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
isolate); isolate);
job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
isolate); isolate);
InsertCodeIntoOptimizedCodeCache(compilation_info); if (V8_LIKELY(use_result)) {
InsertCodeIntoCompilationCache(isolate, compilation_info); InsertCodeIntoOptimizedCodeCache(compilation_info);
CompilerTracer::TraceCompletedJob(isolate, compilation_info); InsertCodeIntoCompilationCache(isolate, compilation_info);
if (should_install_code_on_function) { CompilerTracer::TraceCompletedJob(isolate, compilation_info);
compilation_info->closure()->set_code(*compilation_info->code(), if (should_install_code_on_function) {
kReleaseStore); compilation_info->closure()->set_code(*compilation_info->code(),
kReleaseStore);
}
} }
return CompilationJob::SUCCEEDED; return CompilationJob::SUCCEEDED;
} }
...@@ -3261,11 +3305,13 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job, ...@@ -3261,11 +3305,13 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
DCHECK_EQ(job->state(), CompilationJob::State::kFailed); DCHECK_EQ(job->state(), CompilationJob::State::kFailed);
CompilerTracer::TraceAbortedJob(isolate, compilation_info); CompilerTracer::TraceAbortedJob(isolate, compilation_info);
compilation_info->closure()->set_code(shared->GetCode(), kReleaseStore); if (V8_LIKELY(use_result)) {
// Clear the InOptimizationQueue marker, if it exists. compilation_info->closure()->set_code(shared->GetCode(), kReleaseStore);
if (!CodeKindIsNativeContextIndependentJSFunction(code_kind) && // Clear the InOptimizationQueue marker, if it exists.
compilation_info->closure()->IsInOptimizationQueue()) { if (!CodeKindIsNativeContextIndependentJSFunction(code_kind) &&
compilation_info->closure()->ClearOptimizationMarker(); compilation_info->closure()->IsInOptimizationQueue()) {
compilation_info->closure()->ClearOptimizationMarker();
}
} }
return CompilationJob::FAILED; return CompilationJob::FAILED;
} }
......
...@@ -70,7 +70,8 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final { ...@@ -70,7 +70,8 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
V(TraceTurboAllocation, trace_turbo_allocation, 16) \ V(TraceTurboAllocation, trace_turbo_allocation, 16) \
V(TraceHeapBroker, trace_heap_broker, 17) \ V(TraceHeapBroker, trace_heap_broker, 17) \
V(WasmRuntimeExceptionSupport, wasm_runtime_exception_support, 18) \ V(WasmRuntimeExceptionSupport, wasm_runtime_exception_support, 18) \
V(ConcurrentInlining, concurrent_inlining, 19) V(ConcurrentInlining, concurrent_inlining, 19) \
V(DiscardResultForTesting, discard_result_for_testing, 20)
enum Flag { enum Flag {
#define DEF_ENUM(Camel, Lower, Bit) k##Camel = 1 << Bit, #define DEF_ENUM(Camel, Lower, Bit) k##Camel = 1 << Bit,
......
...@@ -185,6 +185,7 @@ void OptimizingCompileDispatcher::Flush(BlockingBehavior blocking_behavior) { ...@@ -185,6 +185,7 @@ void OptimizingCompileDispatcher::Flush(BlockingBehavior blocking_behavior) {
} }
void OptimizingCompileDispatcher::Stop() { void OptimizingCompileDispatcher::Stop() {
HandleScope handle_scope(isolate_);
FlushQueues(BlockingBehavior::kBlock, false); FlushQueues(BlockingBehavior::kBlock, false);
// At this point the optimizing compiler thread's event loop has stopped. // At this point the optimizing compiler thread's event loop has stopped.
// There is no need for a mutex when reading input_queue_length_. // There is no need for a mutex when reading input_queue_length_.
......
...@@ -80,7 +80,7 @@ class NodeObserver : public ZoneObject { ...@@ -80,7 +80,7 @@ class NodeObserver : public ZoneObject {
bool has_observed_changes() const { return has_observed_changes_; } bool has_observed_changes() const { return has_observed_changes_; }
private: private:
bool has_observed_changes_ = false; std::atomic<bool> has_observed_changes_{false};
}; };
inline NodeObserver::~NodeObserver() = default; inline NodeObserver::~NodeObserver() = default;
......
...@@ -707,6 +707,10 @@ ...@@ -707,6 +707,10 @@
['variant == stress_concurrent_inlining', { ['variant == stress_concurrent_inlining', {
# BUG(11524): Crashing flakily. # BUG(11524): Crashing flakily.
'test-cpu-profiler/TracingCpuProfiler': [PASS, FAIL], 'test-cpu-profiler/TracingCpuProfiler': [PASS, FAIL],
# crbug.com/v8/11513: Flakily failing due to the additional compile task.
'test-heap/EnsureAllocationSiteDependentCodesProcessed': [PASS, FAIL],
'test-heap/LeakNativeContextViaMapProto': [PASS, FAIL],
'test-heap/ObjectsInEagerlyDeoptimizedCodeAreWeak': [PASS, FAIL],
}], # variant == stress_concurrent_inlining }], # variant == stress_concurrent_inlining
] ]
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