Commit d6a02c02 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[predictable] Run worker task on the foreground task runner

On the PredictablePlatform, worker tasks were executed immediately
instead of posting them in a task queue first. This approach caused
problems because the execution of the worker task blocked progress of
the posting task, and the worker task was always executed in the
context of the posting task, e.g. with an already open HandleScope.

With this CL, worker tasks get posted into the foreground task queue
of the nullptr isolate instead of executing them immediately.
The tasks of the nullptr isolate are then executed after a task of
some other task queue is executed. As the worker tasks are thereby
executed on the same thread as foreground tasks, the behavior is
deterministic.

A consequence of this approach is that each pumping the message loop
of an Isolate may also execute other Isolate's background tasks.

This approach is needed because we don't have a BackgroundTaskRunner but
merely a CallOnWorkerThread method that doesn't know which Isolate the
task corresponds to.

R=clemensb@chromium.org, mlippautz@chromium.org

Bug: v8:9670
Change-Id: I6847ae042146431bc2376d27280be8829f529b95
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2182453
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67616}
parent 8aa7a464
...@@ -43,9 +43,17 @@ class PredictablePlatform : public Platform { ...@@ -43,9 +43,17 @@ class PredictablePlatform : public Platform {
int NumberOfWorkerThreads() override { return 0; } int NumberOfWorkerThreads() override { return 0; }
void CallOnWorkerThread(std::unique_ptr<Task> task) override { void CallOnWorkerThread(std::unique_ptr<Task> task) override {
// It's not defined when background tasks are being executed, so we can just // We post worker tasks on the foreground task runner of the
// execute them right away. // {kProcessGlobalPredictablePlatformWorkerTaskQueue} isolate. The task
task->Run(); // queue of the {kProcessGlobalPredictablePlatformWorkerTaskQueue} isolate
// is then executed on the main thread to achieve predictable behavior.
//
// In this context here it is okay to call {GetForegroundTaskRunner} from a
// background thread. The reason is that code is executed sequentially with
// the PredictablePlatform, and that the {DefaultPlatform} does not access
// the isolate but only uses it as the key in a HashMap.
GetForegroundTaskRunner(kProcessGlobalPredictablePlatformWorkerTaskQueue)
->PostTask(std::move(task));
} }
void CallDelayedOnWorkerThread(std::unique_ptr<Task> task, void CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
namespace v8 { namespace v8 {
class Isolate;
class Platform; class Platform;
// Returns a predictable v8::Platform implementation. // Returns a predictable v8::Platform implementation.
...@@ -24,6 +25,13 @@ std::unique_ptr<Platform> MakePredictablePlatform( ...@@ -24,6 +25,13 @@ std::unique_ptr<Platform> MakePredictablePlatform(
std::unique_ptr<Platform> MakeDelayedTasksPlatform( std::unique_ptr<Platform> MakeDelayedTasksPlatform(
std::unique_ptr<Platform> platform, int64_t random_seed); std::unique_ptr<Platform> platform, int64_t random_seed);
// We use the task queue of {kProcessGlobalPredictablePlatformWorkerTaskQueue}
// for worker tasks of the {PredictablePlatform}. At the moment, {nullptr} is a
// valid value for the isolate. If this ever changes, we either have to allocate
// a core isolate, or refactor the implementation of worker tasks in the
// {PredictablePlatform}.
constexpr Isolate* kProcessGlobalPredictablePlatformWorkerTaskQueue = nullptr;
} // namespace v8 } // namespace v8
#endif // V8_D8_D8_PLATFORMS_H_ #endif // V8_D8_D8_PLATFORMS_H_
...@@ -3125,6 +3125,17 @@ bool ProcessMessages( ...@@ -3125,6 +3125,17 @@ bool ProcessMessages(
while (v8::platform::PumpMessageLoop(g_default_platform, isolate, while (v8::platform::PumpMessageLoop(g_default_platform, isolate,
behavior())) { behavior())) {
MicrotasksScope::PerformCheckpoint(isolate); MicrotasksScope::PerformCheckpoint(isolate);
if (i::FLAG_verify_predictable) {
// In predictable mode we push all background tasks into the foreground
// task queue of the {kProcessGlobalPredictablePlatformWorkerTaskQueue}
// isolate. We execute the tasks after one foreground task has been
// executed.
while (v8::platform::PumpMessageLoop(
g_default_platform,
kProcessGlobalPredictablePlatformWorkerTaskQueue, behavior())) {
}
}
} }
if (g_default_platform->IdleTasksEnabled(isolate)) { if (g_default_platform->IdleTasksEnabled(isolate)) {
v8::platform::RunIdleTasks(g_default_platform, isolate, v8::platform::RunIdleTasks(g_default_platform, isolate,
......
...@@ -695,6 +695,7 @@ DEFINE_BOOL(wasm_tier_up, true, ...@@ -695,6 +695,7 @@ DEFINE_BOOL(wasm_tier_up, true,
"enable tier up to the optimizing compiler (requires --liftoff to " "enable tier up to the optimizing compiler (requires --liftoff to "
"have an effect)") "have an effect)")
DEFINE_DEBUG_BOOL(trace_wasm_decoder, false, "trace decoding of wasm code") DEFINE_DEBUG_BOOL(trace_wasm_decoder, false, "trace decoding of wasm code")
DEFINE_IMPLICATION(trace_wasm_decoder, single_threaded)
DEFINE_DEBUG_BOOL(trace_wasm_compiler, false, "trace compiling of wasm code") DEFINE_DEBUG_BOOL(trace_wasm_compiler, false, "trace compiling of wasm code")
DEFINE_DEBUG_BOOL(trace_wasm_interpreter, false, DEFINE_DEBUG_BOOL(trace_wasm_interpreter, false,
"trace interpretation of wasm code") "trace interpretation of wasm code")
...@@ -772,6 +773,7 @@ DEFINE_BOOL(wasm_fuzzer_gen_test, false, ...@@ -772,6 +773,7 @@ DEFINE_BOOL(wasm_fuzzer_gen_test, false,
"generate a test case when running a wasm fuzzer") "generate a test case when running a wasm fuzzer")
DEFINE_IMPLICATION(wasm_fuzzer_gen_test, single_threaded) DEFINE_IMPLICATION(wasm_fuzzer_gen_test, single_threaded)
DEFINE_BOOL(print_wasm_code, false, "Print WebAssembly code") DEFINE_BOOL(print_wasm_code, false, "Print WebAssembly code")
DEFINE_IMPLICATION(print_wasm_code, single_threaded)
DEFINE_BOOL(print_wasm_stub_code, false, "Print WebAssembly stub code") DEFINE_BOOL(print_wasm_stub_code, false, "Print WebAssembly stub code")
DEFINE_BOOL(asm_wasm_lazy_compilation, false, DEFINE_BOOL(asm_wasm_lazy_compilation, false,
"enable lazy compilation for asm-wasm modules") "enable lazy compilation for asm-wasm modules")
......
...@@ -1035,9 +1035,7 @@ bool ExecuteJSToWasmWrapperCompilationUnits( ...@@ -1035,9 +1035,7 @@ bool ExecuteJSToWasmWrapperCompilationUnits(
return true; return true;
} }
bool NeedsDeterministicCompile() { bool NeedsDeterministicCompile() { return FLAG_single_threaded; }
return FLAG_trace_wasm_decoder || FLAG_wasm_num_compilation_tasks <= 1;
}
// Run by the main thread and background tasks to take part in compilation. // Run by the main thread and background tasks to take part in compilation.
// Returns whether any units were executed. // Returns whether any units were executed.
...@@ -1368,15 +1366,11 @@ void CompileNativeModule(Isolate* isolate, ErrorThrower* thrower, ...@@ -1368,15 +1366,11 @@ void CompileNativeModule(Isolate* isolate, ErrorThrower* thrower,
// are part of initial compilation). Otherwise, just execute baseline units. // are part of initial compilation). Otherwise, just execute baseline units.
bool is_tiering = compilation_state->compile_mode() == CompileMode::kTiering; bool is_tiering = compilation_state->compile_mode() == CompileMode::kTiering;
auto baseline_only = is_tiering ? kBaselineOnly : kBaselineOrTopTier; auto baseline_only = is_tiering ? kBaselineOnly : kBaselineOrTopTier;
// The main threads contributes to the compilation, except if we need // The main threads contributes to the compilation.
// deterministic compilation; in that case, the single background task will while (ExecuteCompilationUnits(compilation_state->background_compile_token(),
// execute all compilation. isolate->counters(), kMainThreadTaskId,
if (!NeedsDeterministicCompile()) { baseline_only)) {
while (ExecuteCompilationUnits( // Continue executing compilation units.
compilation_state->background_compile_token(), isolate->counters(),
kMainThreadTaskId, baseline_only)) {
// Continue executing compilation units.
}
} }
// Now wait until baseline compilation finished. // Now wait until baseline compilation finished.
...@@ -1486,15 +1480,11 @@ void RecompileNativeModule(Isolate* isolate, NativeModule* native_module, ...@@ -1486,15 +1480,11 @@ void RecompileNativeModule(Isolate* isolate, NativeModule* native_module,
// We only wait for tier down. Tier up can happen in the background. // We only wait for tier down. Tier up can happen in the background.
if (tiering_state == kTieredDown) { if (tiering_state == kTieredDown) {
// The main thread contributes to the compilation, except if we need // The main thread contributes to the compilation.
// deterministic compilation; in that case, the single background task will while (ExecuteCompilationUnits(
// execute all compilation. compilation_state->background_compile_token(), isolate->counters(),
if (!NeedsDeterministicCompile()) { kMainThreadTaskId, kBaselineOnly)) {
while (ExecuteCompilationUnits( // Continue executing compilation units.
compilation_state->background_compile_token(), isolate->counters(),
kMainThreadTaskId, kBaselineOnly)) {
// Continue executing compilation units.
}
} }
// Now wait until baseline recompilation finished. // Now wait until baseline recompilation finished.
......
...@@ -956,17 +956,10 @@ ...@@ -956,17 +956,10 @@
'regress/regress-356053': [SKIP], 'regress/regress-356053': [SKIP],
'regress/regress-embedded-cons-string': [SKIP], 'regress/regress-embedded-cons-string': [SKIP],
# Relies on async compilation which requires background tasks.
'wasm/streaming-error-position': [SKIP],
# Intentionally non-deterministic using shared arraybuffers. # Intentionally non-deterministic using shared arraybuffers.
'wasm/atomics-stress': [SKIP], 'wasm/atomics-stress': [SKIP],
'wasm/atomics64-stress': [SKIP], 'wasm/atomics64-stress': [SKIP],
'wasm/futex': [SKIP], 'wasm/futex': [SKIP],
# Deadlocks on predictable platform (https://crbug.com/v8/9760).
'wasm/async-compile': [SKIP],
'wasm/streaming-compile': [SKIP],
}], # 'predictable == True' }], # 'predictable == True'
############################################################################## ##############################################################################
......
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