From 1d249e8cb489a73443367df824a038cea349df37 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 29 Jul 2021 11:03:44 +0200 Subject: [PATCH] [runtime][microtask] Various smaller performance tweaks - Make sure we use fast prechecks in the header files - MicrotaskQueue::CallEnqueueMicrotask returns a Smi instead of a more costly undefined value (the return value is enforced by the calling convention, but unused) - Merge FireMicrotasksCompletedCallback into OnComplete Change-Id: I3797b946bcffb6349e5693c41478bd2bad1f93fb Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3024154 Commit-Queue: Camillo Bruni Reviewed-by: Victor Gomes Cr-Commit-Position: refs/heads/master@{#75985} --- src/execution/isolate.cc | 5 ++-- src/execution/isolate.h | 7 +++++- src/execution/microtask-queue.cc | 42 ++++++++++++-------------------- src/execution/microtask-queue.h | 20 ++++++++++----- 4 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc index 5d606d5780..d48753bf50 100644 --- a/src/execution/isolate.cc +++ b/src/execution/isolate.cc @@ -4212,8 +4212,9 @@ void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) { call_completed_callbacks_.erase(pos); } -void Isolate::FireCallCompletedCallback(MicrotaskQueue* microtask_queue) { - if (!thread_local_top()->CallDepthIsZero()) return; +void Isolate::FireCallCompletedCallbackInternal( + MicrotaskQueue* microtask_queue) { + DCHECK(thread_local_top()->CallDepthIsZero()); bool perform_checkpoint = microtask_queue && diff --git a/src/execution/isolate.h b/src/execution/isolate.h index 4bf048535f..44b9e6ff62 100644 --- a/src/execution/isolate.h +++ b/src/execution/isolate.h @@ -1452,7 +1452,10 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { size_t heap_limit); void AddCallCompletedCallback(CallCompletedCallback callback); void RemoveCallCompletedCallback(CallCompletedCallback callback); - void FireCallCompletedCallback(MicrotaskQueue* microtask_queue); + void FireCallCompletedCallback(MicrotaskQueue* microtask_queue) { + if (!thread_local_top()->CallDepthIsZero()) return; + FireCallCompletedCallbackInternal(microtask_queue); + } void AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback); void RemoveBeforeCallEnteredCallback(BeforeCallEnteredCallback callback); @@ -1830,6 +1833,8 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { static void RemoveContextIdCallback(const v8::WeakCallbackInfo& data); + void FireCallCompletedCallbackInternal(MicrotaskQueue* microtask_queue); + class ThreadDataTable { public: ThreadDataTable() = default; diff --git a/src/execution/microtask-queue.cc b/src/execution/microtask-queue.cc index cae642e2c9..68c2c4a09e 100644 --- a/src/execution/microtask-queue.cc +++ b/src/execution/microtask-queue.cc @@ -74,7 +74,7 @@ Address MicrotaskQueue::CallEnqueueMicrotask(Isolate* isolate, Microtask microtask = Microtask::cast(Object(raw_microtask)); reinterpret_cast(microtask_queue_pointer) ->EnqueueMicrotask(microtask); - return ReadOnlyRoots(isolate).undefined_value().ptr(); + return Smi::zero().ptr(); } void MicrotaskQueue::EnqueueMicrotask(v8::Isolate* v8_isolate, @@ -110,23 +110,21 @@ void MicrotaskQueue::EnqueueMicrotask(Microtask microtask) { ++size_; } -void MicrotaskQueue::PerformCheckpoint(v8::Isolate* v8_isolate) { - if (!IsRunningMicrotasks() && !GetMicrotasksScopeDepth() && - !HasMicrotasksSuppressions()) { - std::unique_ptr microtasks_scope; - if (microtasks_policy_ == v8::MicrotasksPolicy::kScoped) { - // If we're using microtask scopes to schedule microtask execution, V8 - // API calls will check that there's always a microtask scope on the - // stack. As the microtasks we're about to execute could invoke embedder - // callbacks which then calls back into V8, we create an artificial - // microtask scope here to avoid running into the CallDepthScope check. - microtasks_scope.reset(new v8::MicrotasksScope( - v8_isolate, this, v8::MicrotasksScope::kDoNotRunMicrotasks)); - } - Isolate* isolate = reinterpret_cast(v8_isolate); - RunMicrotasks(isolate); - isolate->ClearKeptObjects(); +void MicrotaskQueue::PerformCheckpointInternal(v8::Isolate* v8_isolate) { + DCHECK(ShouldPerfomCheckpoint()); + std::unique_ptr microtasks_scope; + if (microtasks_policy_ == v8::MicrotasksPolicy::kScoped) { + // If we're using microtask scopes to schedule microtask execution, V8 + // API calls will check that there's always a microtask scope on the + // stack. As the microtasks we're about to execute could invoke embedder + // callbacks which then calls back into V8, we create an artificial + // microtask scope here to avoid running into the CallDepthScope check. + microtasks_scope.reset(new v8::MicrotasksScope( + v8_isolate, this, v8::MicrotasksScope::kDoNotRunMicrotasks)); } + Isolate* isolate = reinterpret_cast(v8_isolate); + RunMicrotasks(isolate); + isolate->ClearKeptObjects(); } namespace { @@ -226,10 +224,6 @@ void MicrotaskQueue::IterateMicrotasks(RootVisitor* visitor) { } } -int MicrotaskQueue::GetMicrotasksScopeDepth() const { - return microtasks_depth_; -} - void MicrotaskQueue::AddMicrotasksCompletedCallback( MicrotasksCompletedCallbackWithData callback, void* data) { CallbackWithData callback_with_data(callback, data); @@ -250,7 +244,7 @@ void MicrotaskQueue::RemoveMicrotasksCompletedCallback( microtasks_completed_callbacks_.erase(pos); } -void MicrotaskQueue::FireMicrotasksCompletedCallback(Isolate* isolate) const { +void MicrotaskQueue::OnCompleted(Isolate* isolate) const { std::vector callbacks(microtasks_completed_callbacks_); for (auto& callback : callbacks) { callback.first(reinterpret_cast(isolate), callback.second); @@ -263,10 +257,6 @@ Microtask MicrotaskQueue::get(intptr_t index) const { return Microtask::cast(microtask); } -void MicrotaskQueue::OnCompleted(Isolate* isolate) { - FireMicrotasksCompletedCallback(isolate); -} - void MicrotaskQueue::ResizeBuffer(intptr_t new_capacity) { DCHECK_LE(size_, new_capacity); Address* new_ring_buffer = new Address[new_capacity]; diff --git a/src/execution/microtask-queue.h b/src/execution/microtask-queue.h index 82840c2bed..e9d40a924f 100644 --- a/src/execution/microtask-queue.h +++ b/src/execution/microtask-queue.h @@ -30,7 +30,7 @@ class V8_EXPORT_PRIVATE MicrotaskQueue final : public v8::MicrotaskQueue { // Uses raw Address values because it's called via ExternalReference. // {raw_microtask} is a tagged Microtask pointer. - // Returns a tagged Object pointer. + // Returns Smi::kZero due to CallCFunction. static Address CallEnqueueMicrotask(Isolate* isolate, intptr_t microtask_queue_pointer, Address raw_microtask); @@ -40,7 +40,15 @@ class V8_EXPORT_PRIVATE MicrotaskQueue final : public v8::MicrotaskQueue { v8::Local microtask) override; void EnqueueMicrotask(v8::Isolate* isolate, v8::MicrotaskCallback callback, void* data) override; - void PerformCheckpoint(v8::Isolate* isolate) override; + void PerformCheckpoint(v8::Isolate* isolate) override { + if (!ShouldPerfomCheckpoint()) return; + PerformCheckpointInternal(isolate); + } + + bool ShouldPerfomCheckpoint() const { + return !IsRunningMicrotasks() && !GetMicrotasksScopeDepth() && + !HasMicrotasksSuppressions(); + } void EnqueueMicrotask(Microtask microtask); void AddMicrotasksCompletedCallback( @@ -62,7 +70,7 @@ class V8_EXPORT_PRIVATE MicrotaskQueue final : public v8::MicrotaskQueue { // invocation, which happens when depth reaches zero. void IncrementMicrotasksScopeDepth() { ++microtasks_depth_; } void DecrementMicrotasksScopeDepth() { --microtasks_depth_; } - int GetMicrotasksScopeDepth() const override; + int GetMicrotasksScopeDepth() const override { return microtasks_depth_; } // Possibly nested microtasks suppression scopes prevent microtasks // from running. @@ -87,8 +95,6 @@ class V8_EXPORT_PRIVATE MicrotaskQueue final : public v8::MicrotaskQueue { } v8::MicrotasksPolicy microtasks_policy() const { return microtasks_policy_; } - void FireMicrotasksCompletedCallback(Isolate* isolate) const; - intptr_t capacity() const { return capacity_; } intptr_t size() const { return size_; } intptr_t start() const { return start_; } @@ -107,7 +113,9 @@ class V8_EXPORT_PRIVATE MicrotaskQueue final : public v8::MicrotaskQueue { static const intptr_t kMinimumCapacity; private: - void OnCompleted(Isolate* isolate); + void PerformCheckpointInternal(v8::Isolate* v8_isolate); + + void OnCompleted(Isolate* isolate) const; MicrotaskQueue(); void ResizeBuffer(intptr_t new_capacity);