diff --git a/common.gypi b/common.gypi index 73f2702bbebc..9cc324610fdd 100644 --- a/common.gypi +++ b/common.gypi @@ -44,7 +44,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.22', + 'v8_embedder_string': '-node.23', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/execution/microtask-queue.cc b/deps/v8/src/execution/microtask-queue.cc index db261fc87922..3467ed9b3167 100644 --- a/deps/v8/src/execution/microtask-queue.cc +++ b/deps/v8/src/execution/microtask-queue.cc @@ -19,6 +19,7 @@ #include "src/execution/isolate.h" #include "src/handles/handle-scope-implementer-inl.h" #include "src/handles/handles-inl.h" +#include "src/heap/heap-inl.h" #include "src/objects/microtask-inl.h" #include "src/objects/visitors.h" #include "src/roots/roots-inl.h" @@ -165,6 +166,18 @@ void MicrotaskQueue::EnqueueMicrotask(Tagged microtask) { void MicrotaskQueue::PerformCheckpointInternal(v8::Isolate* v8_isolate) { DCHECK(ShouldPerfomCheckpoint()); + DCHECK(!microtasks_completed_callbacks_cow_.has_value()); + Isolate* isolate = reinterpret_cast(v8_isolate); + // Fast path: Checkpoints occur frequently when exiting script or microtask + // scopes. If there are no microtasks to drain, no completion callbacks to + // notify, and no kept objects from FinalizationRegistry / WeakRefs to clear, + // we can bail out immediately and avoid artificial MicrotasksScope setup and + // RunMicrotasks overhead. + if (size() == 0 && microtasks_completed_callbacks_.empty() && + isolate->heap()->weak_refs_keep_during_job() == + ReadOnlyRoots(isolate).undefined_value()) [[likely]] { + return; + } std::optional microtasks_scope; if (microtasks_policy_ == v8::MicrotasksPolicy::kScoped) { // If we're using microtask scopes to schedule microtask execution, V8 @@ -175,7 +188,6 @@ void MicrotaskQueue::PerformCheckpointInternal(v8::Isolate* v8_isolate) { microtasks_scope.emplace(v8_isolate, this, v8::MicrotasksScope::kDoNotRunMicrotasks); } - Isolate* isolate = reinterpret_cast(v8_isolate); RunMicrotasks(isolate); isolate->ClearKeptObjects(); } @@ -347,12 +359,18 @@ void MicrotaskQueue::RemoveMicrotasksCompletedCallback( } void MicrotaskQueue::OnCompleted(Isolate* isolate) { + DCHECK_IMPLIES(microtasks_completed_callbacks_.empty(), + !microtasks_completed_callbacks_cow_.has_value()); + if (microtasks_completed_callbacks_.empty()) [[likely]] { + return; + } + is_running_completed_callbacks_ = true; for (auto& callback : microtasks_completed_callbacks_) { callback.first(reinterpret_cast(isolate), callback.second); } is_running_completed_callbacks_ = false; - if (V8_UNLIKELY(microtasks_completed_callbacks_cow_.has_value())) { + if (microtasks_completed_callbacks_cow_.has_value()) [[unlikely]] { microtasks_completed_callbacks_ = std::move(microtasks_completed_callbacks_cow_.value()); microtasks_completed_callbacks_cow_.reset();