Commit 5f6de71a authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Call callbacks from background

The CompilationState should not be bound to a specific isolate. Hence
it cannot start foreground task. Instead, the callbacks themselves
should do this if they are specific to one Isolate.

R=mstarzinger@chromium.org

Bug: v8:8689, v8:8050
Change-Id: Ic86bba1dd645401b2b284a9f26eec87718b011e1
Reviewed-on: https://chromium-review.googlesource.com/c/1445977
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59225}
parent 7a239468
...@@ -1087,9 +1087,14 @@ class AsyncCompileJob::CompilationStateCallback { ...@@ -1087,9 +1087,14 @@ class AsyncCompileJob::CompilationStateCallback {
case CompilationEvent::kFinishedBaselineCompilation: case CompilationEvent::kFinishedBaselineCompilation:
DCHECK(!last_event_.has_value()); DCHECK(!last_event_.has_value());
if (job_->DecrementAndCheckFinisherCount()) { if (job_->DecrementAndCheckFinisherCount()) {
SaveContext saved_context(job_->isolate()); AsyncCompileJob* job = job_;
job_->isolate()->set_context(*job_->native_context_); job->foreground_task_runner_->PostTask(
job_->FinishCompile(); MakeCancelableTask(job->isolate_, [job] {
HandleScope scope(job->isolate_);
SaveContext saved_context(job->isolate_);
job->isolate_->set_context(*job->native_context_);
job->FinishCompile();
}));
} }
break; break;
case CompilationEvent::kFinishedTopTierCompilation: case CompilationEvent::kFinishedTopTierCompilation:
...@@ -1097,15 +1102,21 @@ class AsyncCompileJob::CompilationStateCallback { ...@@ -1097,15 +1102,21 @@ class AsyncCompileJob::CompilationStateCallback {
// This callback should not react to top tier finished callbacks, since // This callback should not react to top tier finished callbacks, since
// the job might already be gone then. // the job might already be gone then.
break; break;
case CompilationEvent::kFailedCompilation: case CompilationEvent::kFailedCompilation: {
DCHECK(!last_event_.has_value()); DCHECK(!last_event_.has_value());
// Tier-up compilation should not fail if baseline compilation // Tier-up compilation should not fail if baseline compilation
// did not fail. // did not fail.
DCHECK(!Impl(job_->native_module_->compilation_state()) DCHECK(!Impl(job_->native_module_->compilation_state())
->baseline_compilation_finished()); ->baseline_compilation_finished());
job_->DoSync<CompileFailed, kUseExistingForegroundTask>(); AsyncCompileJob* job = job_;
job->foreground_task_runner_->PostTask(
MakeCancelableTask(job->isolate_, [job] {
job->DoSync<CompileFailed, kUseExistingForegroundTask>();
}));
break; break;
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -1117,6 +1128,8 @@ class AsyncCompileJob::CompilationStateCallback { ...@@ -1117,6 +1128,8 @@ class AsyncCompileJob::CompilationStateCallback {
private: private:
AsyncCompileJob* job_; AsyncCompileJob* job_;
#ifdef DEBUG #ifdef DEBUG
// This will be modified by different threads, but they externally
// synchronize, so no explicit synchronization (currently) needed here.
base::Optional<CompilationEvent> last_event_; base::Optional<CompilationEvent> last_event_;
#endif #endif
}; };
...@@ -1699,9 +1712,6 @@ void CompilationStateImpl::OnFinishedUnit(ExecutionTier tier, WasmCode* code) { ...@@ -1699,9 +1712,6 @@ void CompilationStateImpl::OnFinishedUnit(ExecutionTier tier, WasmCode* code) {
// tiering units. // tiering units.
DCHECK_IMPLIES(!is_tiering_mode, outstanding_tiering_units_ == 0); DCHECK_IMPLIES(!is_tiering_mode, outstanding_tiering_units_ == 0);
// Bitset of events to deliver.
base::EnumSet<CompilationEvent> events;
if (is_tiering_unit) { if (is_tiering_unit) {
DCHECK_LT(0, outstanding_tiering_units_); DCHECK_LT(0, outstanding_tiering_units_);
--outstanding_tiering_units_; --outstanding_tiering_units_;
...@@ -1709,35 +1719,23 @@ void CompilationStateImpl::OnFinishedUnit(ExecutionTier tier, WasmCode* code) { ...@@ -1709,35 +1719,23 @@ void CompilationStateImpl::OnFinishedUnit(ExecutionTier tier, WasmCode* code) {
// If baseline compilation has not finished yet, then also trigger // If baseline compilation has not finished yet, then also trigger
// {kFinishedBaselineCompilation}. // {kFinishedBaselineCompilation}.
if (outstanding_baseline_units_ > 0) { if (outstanding_baseline_units_ > 0) {
events.Add(CompilationEvent::kFinishedBaselineCompilation); NotifyOnEvent(CompilationEvent::kFinishedBaselineCompilation);
} }
events.Add(CompilationEvent::kFinishedTopTierCompilation); NotifyOnEvent(CompilationEvent::kFinishedTopTierCompilation);
} }
} else { } else {
DCHECK_LT(0, outstanding_baseline_units_); DCHECK_LT(0, outstanding_baseline_units_);
--outstanding_baseline_units_; --outstanding_baseline_units_;
if (outstanding_baseline_units_ == 0) { if (outstanding_baseline_units_ == 0) {
events.Add(CompilationEvent::kFinishedBaselineCompilation); NotifyOnEvent(CompilationEvent::kFinishedBaselineCompilation);
// If we are not tiering, then we also trigger the "top tier finished" // If we are not tiering, then we also trigger the "top tier finished"
// event when baseline compilation is finished. // event when baseline compilation is finished.
if (!is_tiering_mode) { if (!is_tiering_mode) {
events.Add(CompilationEvent::kFinishedTopTierCompilation); NotifyOnEvent(CompilationEvent::kFinishedTopTierCompilation);
} }
} }
} }
if (!events.empty()) {
auto notify_events = [this, events] {
for (auto event : {CompilationEvent::kFinishedBaselineCompilation,
CompilationEvent::kFinishedTopTierCompilation}) {
if (!events.contains(event)) continue;
NotifyOnEvent(event);
}
};
foreground_task_runner_->PostTask(
MakeCancelableTask(&foreground_task_manager_, notify_events));
}
if (should_log_code_ && code != nullptr) { if (should_log_code_ && code != nullptr) {
engine_->LogCode(code); engine_->LogCode(code);
} }
...@@ -1840,13 +1838,10 @@ void CompilationStateImpl::SetError(uint32_t func_index, ...@@ -1840,13 +1838,10 @@ void CompilationStateImpl::SetError(uint32_t func_index,
compile_error.release(); compile_error.release();
// Schedule a foreground task to call the callback and notify users about the // Schedule a foreground task to call the callback and notify users about the
// compile error. // compile error.
foreground_task_runner_->PostTask(MakeCancelableTask( NotifyOnEvent(CompilationEvent::kFailedCompilation);
&foreground_task_manager_,
[this] { NotifyOnEvent(CompilationEvent::kFailedCompilation); }));
} }
void CompilationStateImpl::NotifyOnEvent(CompilationEvent event) { void CompilationStateImpl::NotifyOnEvent(CompilationEvent event) {
HandleScope scope(isolate_);
for (auto& callback : callbacks_) callback(event); for (auto& callback : callbacks_) callback(event);
// If no more events are expected after this one, clear the callbacks to free // If no more events are expected after this one, clear the callbacks to free
// memory. We can safely do this here, as this method is only called from // memory. We can safely do this here, as this method is only called from
......
...@@ -19,7 +19,9 @@ ...@@ -19,7 +19,9 @@
#include "src/objects/js-promise-inl.h" #include "src/objects/js-promise-inl.h"
#include "src/objects/templates.h" #include "src/objects/templates.h"
#include "src/parsing/parse-info.h" #include "src/parsing/parse-info.h"
#include "src/task-utils.h"
#include "src/trap-handler/trap-handler.h" #include "src/trap-handler/trap-handler.h"
#include "src/v8.h"
#include "src/wasm/streaming-decoder.h" #include "src/wasm/streaming-decoder.h"
#include "src/wasm/wasm-engine.h" #include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-limits.h" #include "src/wasm/wasm-limits.h"
...@@ -69,15 +71,24 @@ class WasmStreaming::WasmStreamingImpl { ...@@ -69,15 +71,24 @@ class WasmStreaming::WasmStreamingImpl {
void SetClient(std::shared_ptr<Client> client) { void SetClient(std::shared_ptr<Client> client) {
// There are no other event notifications so just pass client to decoder. // There are no other event notifications so just pass client to decoder.
// Wrap the client with a callback here so we can also wrap the result. // Wrap the client with a callback to trigger the callback in a new
// foreground task.
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
v8::Platform* platform = i::V8::GetCurrentPlatform();
std::shared_ptr<TaskRunner> foreground_task_runner =
platform->GetForegroundTaskRunner(isolate_);
streaming_decoder_->SetModuleCompiledCallback( streaming_decoder_->SetModuleCompiledCallback(
[client](const std::shared_ptr<i::wasm::NativeModule>& native_module) { [client, i_isolate, foreground_task_runner](
client->OnModuleCompiled(Utils::Convert(native_module)); const std::shared_ptr<i::wasm::NativeModule>& native_module) {
foreground_task_runner->PostTask(
i::MakeCancelableTask(i_isolate, [client, native_module] {
client->OnModuleCompiled(Utils::Convert(native_module));
}));
}); });
} }
private: private:
Isolate* isolate_ = nullptr; Isolate* const isolate_;
std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_; std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_;
std::shared_ptr<internal::wasm::CompilationResultResolver> resolver_; std::shared_ptr<internal::wasm::CompilationResultResolver> resolver_;
}; };
......
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