27MaybeDirectHandle<JSReceiver> PerformPromiseThen(
28 Isolate* isolate, DirectHandle<JSReceiver> promise,
29 DirectHandle<Object> fulfill_handler,
30 MaybeDirectHandle<JSFunction> maybe_reject_handler = {}) {
31 DCHECK(IsCallable(*fulfill_handler));
32 DirectHandle<Object> reject_handler = isolate->factory()->undefined_value();
33 if (!maybe_reject_handler.is_null()) {
34 reject_handler = maybe_reject_handler.ToHandleChecked();
36 DirectHandle<Object>
args[] = {fulfill_handler, reject_handler};
38 DirectHandle<Object> then_result;
47MaybeDirectHandle<Context> SetAsyncUnlockHandlers(
48 Isolate* isolate, DirectHandle<JSAtomicsMutex>
mutex,
49 DirectHandle<JSReceiver> waiting_for_callback_promise,
50 DirectHandle<JSPromise> unlocked_promise) {
51 DirectHandle<Context> handlers_context =
52 isolate->factory()->NewBuiltinContext(
58 DirectHandle<SharedFunctionInfo> resolve_info(
59 isolate->heap()->atomics_mutex_async_unlock_resolve_handler_sfi(),
61 DirectHandle<JSFunction> resolver_callback =
62 Factory::JSFunctionBuilder{
isolate, resolve_info, handlers_context}
63 .set_map(isolate->strict_function_without_prototype_map())
67 DirectHandle<SharedFunctionInfo> reject_info(
68 isolate->heap()->atomics_mutex_async_unlock_reject_handler_sfi(),
70 DirectHandle<JSFunction> reject_callback =
71 Factory::JSFunctionBuilder{
isolate, reject_info, handlers_context}
72 .set_map(isolate->strict_function_without_prototype_map())
77 PerformPromiseThen(isolate, waiting_for_callback_promise,
78 resolver_callback, reject_callback));
79 return handlers_context;
82void AddPromiseToNativeContext(Isolate* isolate,
83 DirectHandle<JSPromise> promise) {
84 DirectHandle<NativeContext>
native_context(isolate->native_context());
91void RemovePromiseFromNativeContext(Isolate* isolate,
92 DirectHandle<JSPromise> promise) {
94 isolate->native_context()->atomics_waitasync_promises(), isolate);
99 isolate->native_context()->set_atomics_waitasync_promises(*promises);
103Global<T> GetWeakGlobal(Isolate* isolate, Local<T>
object) {
126 :
state_(state), new_state_(kInvalidState) {
127 while (!JSSynchronizationPrimitive::TryLockWaiterQueueExplicit(
128 state, current_state)) {
136 :
state_(state), new_state_(kInvalidState) {
138 DCHECK(JSSynchronizationPrimitive::IsWaiterQueueLockedField::decode(
148 DCHECK(JSSynchronizationPrimitive::IsWaiterQueueLockedField::decode(
150 new_state_ = JSSynchronizationPrimitive::IsWaiterQueueLockedField::update(
152 state_->store(new_state_, std::memory_order_release);
157 static std::optional<WaiterQueueLockGuard>
159 return std::optional<WaiterQueueLockGuard>(std::in_place, state,
true);
176 requester_->main_thread_local_heap()->ExecuteWhileParked([
this]() {
178 while (should_wait_) {
179 wait_cond_var_.Wait(&wait_lock_);
188 requester_->main_thread_local_heap()->ExecuteWhileParked([
this, rel_time,
198 current_time = base::TimeTicks::Now();
199 if (current_time >= timeout_time) {
204 bool wait_res = wait_cond_var_.WaitFor(&wait_lock_, time_until_timeout);
214 should_wait_ =
false;
215 wait_cond_var_.NotifyOne();
216 SetNotInListForVerification();
242 typename T::AsyncWaiterNodeType* node)
246 if (
node_->requester_->cancelable_task_manager()->canceled())
return;
247 T::HandleAsyncNotify(
node_);
251 typename T::AsyncWaiterNodeType*
node_;
257 typename T::AsyncWaiterNodeType* node)
261 if (
node_->requester_->cancelable_task_manager()->canceled())
return;
262 T::HandleAsyncTimeout(
node_);
266 typename T::AsyncWaiterNodeType*
node_;
278 requester, synchronization_primitive, internal_waiting_promise,
289 DCHECK(IsJSAtomicsMutex(*synchronization_primitive));
290 auto waiter = std::unique_ptr<AsyncWaiterQueueNode<T>>(
307 Utils::OpenHandle(*internal_waiting_promise_.Get(v8_isolate));
308 return internal_waiting_promise;
311 bool IsEmpty()
const {
return synchronization_primitive_.IsEmpty(); }
316 Cast<T>(Utils::OpenHandle(*synchronization_primitive_.Get(v8_isolate)));
317 return synchronization_primitive;
323 Cast<JSPromise>(Utils::OpenHandle(*unlocked_promise_.Get(v8_isolate)));
324 return unlocked_promise;
328 SetNotInListForVerification();
330 if (task_manager->
canceled())
return;
332 std::make_unique<AsyncWaiterNotifyTask<T>>(task_manager,
this);
333 notify_task_id_ = notify_task->id();
334 task_runner_->PostNonNestableTask(std::move(notify_task));
342 T::CleanupMatchingAsyncWaiters(requester_,
this, matcher);
349 node->requester_->async_waiter_queue_nodes().remove_if(
350 [=](std::unique_ptr<WaiterQueueNode>& n) {
return n.get() ==
node; });
364 GetWeakGlobal(requester, Utils::ToLocal(requester->
native_context()));
365 synchronization_primitive_ = GetWeakGlobal(
366 requester, Utils::ToLocal(Cast<JSObject>(synchronization_primitive)));
377 V8::GetCurrentPlatform()->GetForegroundTaskRunner(v8_isolate);
378 timeout_task_id_ = CancelableTaskManager::kInvalidTaskId;
380 GetWeakGlobal(requester, Utils::ToLocal(requester->
native_context()));
381 synchronization_primitive_ = GetWeakGlobal(
382 requester, Utils::ToLocal(Cast<JSObject>(synchronization_primitive)));
383 internal_waiting_promise_ = GetWeakGlobal(
384 requester, Utils::PromiseToLocal(internal_waiting_promise));
385 if (!unlocked_promise.
is_null()) {
386 DCHECK(IsJSAtomicsMutex(*synchronization_primitive));
387 unlocked_promise_ = GetWeakGlobal(
397 bool ready_for_async_cleanup_ =
false;
422 return waiter->IsSameIsolateForAsyncCleanup(isolate);
429 std::list<std::unique_ptr<WaiterQueueNode>>& async_waiter_queue_nodes_list =
430 isolate->async_waiter_queue_nodes();
431 if (!async_waiter_queue_nodes_list.empty()) {
435 auto it = async_waiter_queue_nodes_list.begin();
436 while (it != async_waiter_queue_nodes_list.end()) {
438 if (!matcher(async_node)) {
442 async_node->CleanupMatchingAsyncWaiters(matcher);
443 it = async_waiter_queue_nodes_list.erase(it);
450 std::atomic<StateT>* state,
StateT& expected) {
453 return state->compare_exchange_weak(
455 std::memory_order_acquire, std::memory_order_relaxed);
460 std::atomic<StateT>* state,
StateT new_state) {
463 StateT expected = state->load(std::memory_order_relaxed);
466 desired = new_state | (expected & ~kWaiterQueueMask);
467 }
while (!state->compare_exchange_weak(
468 expected, desired, std::memory_order_release, std::memory_order_relaxed));
475 StateT current_state = state->load(std::memory_order_acquire);
519 isolate->factory()->NewJSObject(isolate->object_function());
531 DequeueMatcher matcher) {
533 if (async_node->ready_for_async_cleanup_) {
540 if (async_node->IsEmpty()) {
543 async_node->SetNotInListForVerification();
547 async_node->GetSynchronizationPrimitive();
548 std::atomic<StateT>* state =
mutex->AtomicStatePtr();
549 StateT current_state = state->load(std::memory_order_relaxed);
553 while (!TryLockWaiterQueueExplicit(state, current_state)) {
557 bool was_locked_by_this_thread =
mutex->IsCurrentThreadOwner();
559 mutex->DestructivelyGetWaiterQueueHead(isolate);
563 if (!async_node->ready_for_async_cleanup_) {
568 was_locked_by_this_thread)) {
577 new_state =
mutex->SetWaiterQueueHead(isolate, waiter_head, new_state);
578 new_state = IsWaiterQueueLockedField::update(new_state,
false);
579 if (was_locked_by_this_thread) {
580 mutex->ClearOwnerThread();
582 state->store(new_state, std::memory_order_release);
584 SetWaiterQueueStateOnly(state, new_state);
593 return state->compare_exchange_weak(
595 std::memory_order_acquire, std::memory_order_relaxed);
600 std::atomic<StateT>* state) {
602 constexpr int kSpinCount = 64;
603 constexpr int kMaxBackoff = 16;
607 StateT current_state = state->load(std::memory_order_relaxed);
611 for (
int yields = 0; yields < backoff; yields++) {
616 backoff = std::min(kMaxBackoff, backoff << 1);
617 }
while (tries < kSpinCount);
623 std::atomic<StateT>* state,
627 StateT current_state = state->load(std::memory_order_relaxed);
628 std::optional<WaiterQueueLockGuard> waiter_queue_lock_guard =
630 if (!waiter_queue_lock_guard.has_value()) {
638 mutex->DestructivelyGetWaiterQueueHead(requester);
643 IsWaiterQueueLockedField::update(current_state,
true));
645 mutex->SetWaiterQueueHead(requester, waiter_head, current_state);
650 waiter_queue_lock_guard->set_new_state(new_state);
656 std::atomic<StateT>* state, StateT& current_state) {
659 TryLockWaiterQueueExplicit(state, current_state)) {
670 Isolate* requester, std::atomic<StateT>* state,
673 StateT current_state = state->load(std::memory_order_relaxed);
675 if (!HasWaitersField::decode(current_state))
return false;
679 while (!TryLockWaiterQueueExplicit(state, current_state)) {
683 WaiterQueueNode* waiter_head = DestructivelyGetWaiterQueueHead(requester);
685 if (waiter_head ==
nullptr) {
688 DCHECK(!HasWaitersField::decode(current_state));
699 IsWaiterQueueLockedField::update(current_state,
true));
701 new_state = SetWaiterQueueHead(requester, waiter_head, new_state);
703 if (!dequeued_node) {
716 DCHECK(!IsWaiterQueueLockedField::decode(new_state));
718 if (state->compare_exchange_strong(current_state, new_state,
719 std::memory_order_acq_rel,
720 std::memory_order_relaxed)) {
727 state->store(new_state, std::memory_order_release);
731 SetWaiterQueueStateOnly(state, new_state);
738 std::atomic<StateT>* state,
739 std::optional<base::TimeDelta> timeout) {
756 rv = this_waiter.
WaitFor(*timeout);
759 state =
mutex->AtomicStatePtr();
763 rv =
mutex->LockJSMutexOrDequeueTimedOutWaiter(requester, state,
771 state =
mutex->AtomicStatePtr();
781 std::atomic<StateT>* state) {
788 StateT current_state = state->load(std::memory_order_relaxed);
791 if (!HasWaitersField::decode(current_state)) {
799 WaiterQueueNode* waiter_head = DestructivelyGetWaiterQueueHead(requester);
806 new_state = SetWaiterQueueHead(requester, waiter_head, new_state);
828 requester, waiting_for_callback_promise,
829 PerformPromiseThen(requester, internal_locked_promise,
callback));
837 requester, handlers_context,
838 SetAsyncUnlockHandlers(requester,
mutex, waiting_for_callback_promise,
841 bool locked =
LockAsync(requester,
mutex, internal_locked_promise,
842 unlocked_promise, &waiter_node, timeout);
855 reinterpret_cast<Address>(waiter_node));
858 return unlocked_promise;
867 std::optional<base::TimeDelta> timeout) {
869 LockImpl(requester,
mutex, timeout, [=](std::atomic<StateT>* state) {
871 internal_locked_promise, unlocked_promise,
872 waiter_node, timeout);
879 internal_locked_promise, requester->
factory()->undefined_value());
886 AddPromiseToNativeContext(requester, internal_locked_promise);
897 LockAsync(requester,
mutex, internal_locked_promise, {}, &waiter_node);
898 return internal_locked_promise;
907 std::optional<base::TimeDelta> timeout) {
919 isolate,
mutex, internal_locked_promise, unlocked_promise);
927 auto task = std::make_unique<AsyncLockTimeoutTask>(
928 isolate->cancelable_task_manager(), this_waiter);
931 timeout->InSecondsF());
933 *waiter_node = this_waiter;
941 std::atomic<StateT>* state =
mutex->AtomicStatePtr();
982 StateT current_state = state->load(std::memory_order_relaxed);
984 if (!HasWaitersField::decode(current_state))
return false;
988 while (!TryLockWaiterQueueExplicit(state, current_state)) {
994 mutex->DestructivelyGetWaiterQueueHead(requester);
996 if (waiter_head ==
nullptr) {
999 DCHECK(!HasWaitersField::decode(current_state));
1010 IsWaiterQueueLockedField::update(current_state,
true));
1012 new_state =
mutex->SetWaiterQueueHead(requester, waiter_head, new_state);
1014 SetWaiterQueueStateOnly(state, new_state);
1015 return dequeued_node !=
nullptr;
1035 requester, js_mutex, js_mutex->AtomicStatePtr(), waiter);
1049 requester, requester->
factory()->undefined_value(),
false);
1051 USE(resolve_result);
1053 RemovePromiseFromNativeContext(requester, lock_promise);
1068 std::atomic<StateT>* state = js_mutex->AtomicStatePtr();
1069 StateT current_state = state->load(std::memory_order_acquire);
1070 if (HasWaitersField::decode(current_state)) {
1074 while (!TryLockWaiterQueueExplicit(state, current_state)) {
1078 js_mutex->DestructivelyGetWaiterQueueHead(requester);
1084 js_mutex->SetWaiterQueueHead(requester, waiter_head, kEmptyState);
1085 new_state = IsWaiterQueueLockedField::update(new_state,
false);
1086 SetWaiterQueueStateOnly(state, new_state);
1112 js_mutex->SetCurrentThreadAsOwner();
1113 auto resolve_result =
1115 USE(resolve_result);
1116 RemovePromiseFromNativeContext(requester, promise);
1123 DequeueMatcher matcher) {
1125 if (async_node->ready_for_async_cleanup_) {
1130 if (async_node->IsEmpty()) {
1133 async_node->SetNotInListForVerification();
1137 async_node->GetSynchronizationPrimitive();
1138 std::atomic<StateT>* state = cv->AtomicStatePtr();
1139 StateT current_state = state->load(std::memory_order_relaxed);
1143 WaiterQueueNode* waiter_head = cv->DestructivelyGetWaiterQueueHead(isolate);
1148 cv->SetWaiterQueueHead(isolate, waiter_head, current_state);
1158 std::atomic<StateT>* state = cv->AtomicStatePtr();
1161 StateT current_state = state->load(std::memory_order_relaxed);
1165 WaiterQueueNode* waiter_head = cv->DestructivelyGetWaiterQueueHead(requester);
1170 IsWaiterQueueLockedField::update(current_state,
true));
1172 cv->SetWaiterQueueHead(requester, waiter_head, current_state);
1180 std::optional<base::TimeDelta> timeout) {
1193 mutex->Unlock(requester);
1195 rv = this_waiter.
WaitFor(*timeout);
1199 std::atomic<StateT>* state = cv->AtomicStatePtr();
1205 return dequeued ? 1 : 0;
1220 std::atomic<StateT>* state,
const DequeueAction& action_under_lock) {
1222 StateT current_state = state->load(std::memory_order_relaxed);
1224 if (!HasWaitersField::decode(current_state))
return 0;
1228 WaiterQueueNode* waiter_head = cv->DestructivelyGetWaiterQueueHead(requester);
1232 if (waiter_head ==
nullptr) {
1233 StateT new_state = kEmptyState;
1238 uint32_t num_dequeued_waiters = action_under_lock(&waiter_head);
1242 IsWaiterQueueLockedField::update(current_state,
true));
1244 cv->SetWaiterQueueHead(requester, waiter_head, current_state);
1247 return num_dequeued_waiters;
1254 std::atomic<StateT>* state = cv->AtomicStatePtr();
1258 requester, cv, state, [=](
WaiterQueueNode** waiter_head) -> uint32_t {
1262 if (!old_head)
return 0;
1267 old_head = *waiter_head;
1268 *waiter_head =
nullptr;
1272 if (!old_head)
return 0;
1275 return old_head->NotifyAllInList();
1290 std::optional<base::TimeDelta> timeout) {
1300 requester->
heap()->atomics_condition_acquire_lock_sfi(), requester);
1303 .
set_map(requester->strict_function_without_prototype_map())
1309 requester, lock_promise,
1310 PerformPromiseThen(requester, internal_waiting_promise, lock_function));
1316 requester, cv, internal_waiting_promise);
1321 auto task = std::make_unique<AsyncWaitTimeoutTask>(
1325 timeout->InSecondsF());
1327 mutex->Unlock(requester);
1329 AddPromiseToNativeContext(requester, internal_waiting_promise);
1330 return lock_promise;
1345 std::atomic<StateT>* state = cv->AtomicStatePtr();
1346 uint32_t num_dequeued =
1350 return dequeued ? 1 : 0;
1354 if (num_dequeued == 0) {
1390 RemovePromiseFromNativeContext(requester, promise);
void PostNonNestableDelayedTask(std::unique_ptr< Task > task, double delay_in_seconds, const SourceLocation &location=SourceLocation::Current())
V8_INLINE bool IsEmpty() const
static constexpr T decode(U value)
static V8_NODISCARD constexpr U update(U previous, T value)
static constexpr Id kInvalidTaskId
TryAbortResult TryAbort(Id id)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > CallBuiltin(Isolate *isolate, DirectHandle< JSFunction > builtin, DirectHandle< Object > receiver, base::Vector< const DirectHandle< Object > > args)
JSFunctionBuilder & set_map(DirectHandle< Map > v)
V8_WARN_UNUSED_RESULT Handle< JSFunction > Build()
DirectHandle< Context > NewBuiltinContext(DirectHandle< NativeContext > native_context, int length)
Handle< Foreign > NewForeign(Address addr, AllocationType allocation_type=AllocationType::kYoung)
Handle< JSPromise > NewJSPromise()
std::list< std::unique_ptr< detail::WaiterQueueNode > > & async_waiter_queue_nodes()
Handle< NativeContext > native_context()
CancelableTaskManager * cancelable_task_manager()
v8::internal::Factory * factory()
@ kConditionVariableAsyncContextSlot
static V8_EXPORT_PRIVATE MaybeDirectHandle< JSReceiver > WaitAsync(Isolate *requester, DirectHandle< JSAtomicsCondition > cv, DirectHandle< JSAtomicsMutex > mutex, std::optional< base::TimeDelta > timeout)
static void QueueWaiter(Isolate *requester, DirectHandle< JSAtomicsCondition > cv, WaiterQueueNode *waiter)
static uint32_t DequeueExplicit(Isolate *requester, DirectHandle< JSAtomicsCondition > cv, std::atomic< StateT > *state, const DequeueAction &dequeue_action)
static void HandleAsyncNotify(WaitAsyncWaiterQueueNode *node)
std::function< uint32_t(WaiterQueueNode **)> DequeueAction
static constexpr uint32_t kAllWaiters
static void CleanupMatchingAsyncWaiters(Isolate *isolate, WaiterQueueNode *node, DequeueMatcher matcher)
static void HandleAsyncTimeout(WaitAsyncWaiterQueueNode *node)
static V8_EXPORT_PRIVATE uint32_t Notify(Isolate *requester, DirectHandle< JSAtomicsCondition > cv, uint32_t count)
static V8_EXPORT_PRIVATE bool WaitFor(Isolate *requester, DirectHandle< JSAtomicsCondition > cv, DirectHandle< JSAtomicsMutex > mutex, std::optional< base::TimeDelta > timeout)
static DirectHandle< JSPromise > LockAsyncWrapperForWait(Isolate *requester, DirectHandle< JSAtomicsMutex > mutex)
static void HandleAsyncTimeout(LockAsyncWaiterQueueNode *node)
void UnlockAsyncLockedMutex(Isolate *requester, DirectHandle< Foreign > async_locked_waiter_wrapper)
static bool TryLockExplicit(std::atomic< StateT > *state, StateT &expected)
static void HandleAsyncNotify(LockAsyncWaiterQueueNode *node)
static V8_EXPORT_PRIVATE bool MaybeEnqueueNode(Isolate *requester, DirectHandle< JSAtomicsMutex > mutex, std::atomic< StateT > *state, WaiterQueueNode *this_waiter)
static bool Lock(Isolate *requester, DirectHandle< JSAtomicsMutex > mutex, std::optional< base::TimeDelta > timeout=std::nullopt)
V8_EXPORT_PRIVATE void UnlockSlowPath(Isolate *requester, std::atomic< StateT > *state)
bool LockJSMutexOrDequeueTimedOutWaiter(Isolate *requester, std::atomic< StateT > *state, WaiterQueueNode *timed_out_waiter)
static bool LockImpl(Isolate *requester, DirectHandle< JSAtomicsMutex > mutex, std::optional< base::TimeDelta > timeout, LockSlowPathWrapper slow_path_wrapper)
static DirectHandle< JSObject > CreateResultObject(Isolate *isolate, DirectHandle< Object > value, bool success)
static std::optional< WaiterQueueLockGuard > LockWaiterQueueOrJSMutex(std::atomic< StateT > *state, StateT ¤t_state)
static void CleanupMatchingAsyncWaiters(Isolate *isolate, WaiterQueueNode *node, DequeueMatcher matcher)
static bool LockOrEnqueueAsyncNode(Isolate *isolate, DirectHandle< JSAtomicsMutex > mutex, LockAsyncWaiterQueueNode *node)
void Unlock(Isolate *requester)
static bool LockAsync(Isolate *requester, DirectHandle< JSAtomicsMutex > mutex, Handle< JSPromise > internal_locked_promise, MaybeHandle< JSPromise > unlocked_promise, AsyncWaiterNodeType **waiter_node, std::optional< base::TimeDelta > timeout=std::nullopt)
std::atomic< int32_t > * AtomicOwnerThreadIdPtr()
static bool DequeueTimedOutAsyncWaiter(Isolate *requester, DirectHandle< JSAtomicsMutex > mutex, std::atomic< StateT > *state, WaiterQueueNode *timed_out_waiter)
static bool LockAsyncSlowPath(Isolate *isolate, DirectHandle< JSAtomicsMutex > mutex, std::atomic< StateT > *state, Handle< JSPromise > internal_locked_promise, MaybeHandle< JSPromise > unlocked_promise, AsyncWaiterNodeType **waiter_node, std::optional< base::TimeDelta > timeout)
@ kUnlockedPromiseAsyncContextSlot
@ kAsyncLockedWaiterAsyncContextSlot
static V8_EXPORT_PRIVATE bool LockSlowPath(Isolate *requester, DirectHandle< JSAtomicsMutex > mutex, std::atomic< StateT > *state, std::optional< base::TimeDelta > timeout)
static constexpr StateT kUnlockedUncontended
bool IsCurrentThreadOwner()
static MaybeDirectHandle< JSPromise > LockOrEnqueuePromise(Isolate *isolate, DirectHandle< JSAtomicsMutex > mutex, DirectHandle< Object > callback, std::optional< base::TimeDelta > timeout)
static V8_INLINE bool BackoffTryLock(Isolate *requester, DirectHandle< JSAtomicsMutex > mutex, std::atomic< StateT > *state)
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > Resolve(DirectHandle< JSPromise > promise, DirectHandle< Object > resolution)
static void CleanupAsyncWaiterLists(Isolate *isolate, DequeueMatcher matcher)
static bool TryLockWaiterQueueExplicit(std::atomic< StateT > *state, StateT &expected)
static constexpr StateT kWaiterQueueMask
static constexpr StateT kEmptyState
WaiterQueueNode * DestructivelyGetWaiterQueueHead(Isolate *requester)
static void SetWaiterQueueStateOnly(std::atomic< StateT > *state, StateT new_state)
std::function< bool(WaiterQueueNode *)> DequeueMatcher
Tagged< Object > NumWaitersForTesting(Isolate *requester)
StateT SetWaiterQueueHead(Isolate *requester, WaiterQueueNode *waiter_head, StateT new_state)
std::atomic< StateT > * AtomicStatePtr()
static void IsolateDeinit(Isolate *isolate)
V8_INLINE DirectHandle< T > ToHandleChecked() const
V8_INLINE bool is_null() const
static HandleType< OrderedHashSet >::MaybeType Add(Isolate *isolate, HandleType< OrderedHashSet > table, DirectHandle< Object > value)
static HandleType< OrderedHashSet > Shrink(Isolate *isolate, HandleType< OrderedHashSet > table)
static bool Delete(Isolate *isolate, Tagged< OrderedHashSet > table, Tagged< Object > key)
static constexpr Tagged< Smi > FromInt(int value)
static constexpr ThreadId Invalid()
void RunInternal() override
AsyncWaiterNotifyTask(CancelableTaskManager *cancelable_task_manager, typename T::AsyncWaiterNodeType *node)
T::AsyncWaiterNodeType * node_
Global< v8::Context > native_context_
static AsyncWaiterQueueNode< T > * NewAsyncWaiterStoredInIsolate(Isolate *requester, DirectHandle< T > synchronization_primitive, Handle< JSPromise > internal_waiting_promise, MaybeHandle< JSPromise > unlocked_promise={})
std::shared_ptr< TaskRunner > task_runner_
Local< v8::Context > GetNativeContext()
friend JSAtomicsCondition
Handle< JSPromise > GetInternalWaitingPromise()
void CleanupMatchingAsyncWaiters(const DequeueMatcher &matcher) override
static void RemoveFromAsyncWaiterQueueList(AsyncWaiterQueueNode< T > *node)
AsyncWaiterQueueNode(Isolate *requester, DirectHandle< T > synchronization_primitive)
Global< v8::Promise > internal_waiting_promise_
CancelableTaskManager::Id notify_task_id_
Global< v8::Promise > unlocked_promise_
Handle< T > GetSynchronizationPrimitive()
CancelableTaskManager::Id timeout_task_id_
static AsyncWaiterQueueNode< T > * NewLockedAsyncWaiterStoredInIsolate(Isolate *requester, DirectHandle< T > synchronization_primitive)
TaskRunner * task_runner()
Handle< JSPromise > GetUnlockedPromise()
Global< v8::Object > synchronization_primitive_
AsyncWaiterQueueNode(Isolate *requester, DirectHandle< T > synchronization_primitive, DirectHandle< JSPromise > internal_waiting_promise, MaybeDirectHandle< JSPromise > unlocked_promise)
void SetReadyForAsyncCleanup() override
bool IsSameIsolateForAsyncCleanup(Isolate *isolate) override
void RunInternal() override
T::AsyncWaiterNodeType * node_
AsyncWaiterTimeoutTask(CancelableTaskManager *cancelable_task_manager, typename T::AsyncWaiterNodeType *node)
base::ConditionVariable wait_cond_var_
void CleanupMatchingAsyncWaiters(const DequeueMatcher &matcher) override
SyncWaiterQueueNode(Isolate *requester)
bool IsSameIsolateForAsyncCleanup(Isolate *isolate) override
void SetReadyForAsyncCleanup() override
bool WaitFor(const base::TimeDelta &rel_time)
void set_new_state(StateT new_state)
WaiterQueueLockGuard(std::atomic< StateT > *state, bool is_locked)
WaiterQueueLockGuard(std::atomic< StateT > *state, StateT ¤t_state)
WaiterQueueLockGuard(const WaiterQueueLockGuard &)=delete
JSSynchronizationPrimitive::StateT StateT
std::atomic< StateT > * state_
WaiterQueueLockGuard()=delete
static std::optional< WaiterQueueLockGuard > NewAlreadyLockedWaiterQueueLockGuard(std::atomic< StateT > *state)
static void DequeueAllMatchingForAsyncCleanup(WaiterQueueNode **head, const DequeueMatcher &matcher)
std::function< bool(WaiterQueueNode *)> DequeueMatcher
static void Enqueue(WaiterQueueNode **head, WaiterQueueNode *new_tail)
static int LengthFromHead(WaiterQueueNode *head)
static WaiterQueueNode * Dequeue(WaiterQueueNode **head)
static WaiterQueueNode * DequeueMatching(WaiterQueueNode **head, const DequeueMatcher &matcher)
static WaiterQueueNode * Split(WaiterQueueNode **head, uint32_t count)
Tagged< NativeContext > native_context_
Handle< SharedFunctionInfo > info
enum v8::internal::@1270::DeoptimizableCodeIterator::@67 state_
#define RETURN_ON_EXCEPTION(isolate, call)
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
base::Vector< const DirectHandle< Object > > args
ZoneVector< RpoNumber > & result
constexpr Vector< T > VectorOf(T *start, size_t size)
!IsContextMap !IsContextMap native_context
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define V8_UNLIKELY(condition)