13std::optional<base::TimeDelta> GetTimeoutDelta(
 
   14    DirectHandle<Object> timeout_obj) {
 
   16  if (!std::isnan(ms)) {
 
   18    if (ms <= 
static_cast<double>(std::numeric_limits<int64_t>::max())) {
 
   25DirectHandle<JSPromise> UnlockAsyncLockedMutexFromPromiseHandler(
 
   27  DirectHandle<Context> 
context(isolate->context(), isolate);
 
   28  DirectHandle<Object> 
mutex(
 
   30  DirectHandle<Object> unlock_promise(
 
   32  DirectHandle<Object> waiter_wrapper_obj(
 
   38  auto async_locked_waiter_wrapper = 
Cast<Foreign>(waiter_wrapper_obj);
 
   39  js_mutex->UnlockAsyncLockedMutex(isolate, async_locked_waiter_wrapper);
 
   40  return js_unlock_promise;
 
   48  return *isolate->factory()->NewJSAtomicsMutex();
 
 
   53  constexpr char method_name[] = 
"Atomics.Mutex.lock";
 
   57  if (!IsJSAtomicsMutex(*js_mutex_obj)) {
 
   59        isolate, NewTypeError(MessageTemplate::kMethodInvokedOnWrongType,
 
   60                              isolate->factory()->NewStringFromAsciiChecked(
 
   65  if (!IsCallable(*run_under_lock)) {
 
   67        isolate, NewTypeError(MessageTemplate::kNotCallable, run_under_lock));
 
   74  if (!isolate->allow_atomics_wait() || js_mutex->IsCurrentThreadOwner()) {
 
   76        isolate, NewTypeError(MessageTemplate::kAtomicsOperationNotAllowed,
 
   77                              isolate->factory()->NewStringFromAsciiChecked(
 
   87                        isolate->factory()->undefined_value(), {}));
 
 
   95  constexpr char method_name[] = 
"Atomics.Mutex.tryLock";
 
   99  if (!IsJSAtomicsMutex(*js_mutex_obj)) {
 
  101        isolate, NewTypeError(MessageTemplate::kMethodInvokedOnWrongType,
 
  102                              isolate->factory()->NewStringFromAsciiChecked(
 
  107  if (!IsCallable(*run_under_lock)) {
 
  109        isolate, NewTypeError(MessageTemplate::kNotCallable, run_under_lock));
 
  116    if (try_lock_guard.
locked()) {
 
  118          isolate, callback_result,
 
  120                          isolate->factory()->undefined_value(), {}));
 
  123      callback_result = isolate->factory()->undefined_value();
 
 
  134  constexpr char method_name[] = 
"Atomics.Mutex.lockWithTimeout";
 
  138  if (!IsJSAtomicsMutex(*js_mutex_obj)) {
 
  140        isolate, NewTypeError(MessageTemplate::kMethodInvokedOnWrongType,
 
  141                              isolate->factory()->NewStringFromAsciiChecked(
 
  146  if (!IsCallable(*run_under_lock)) {
 
  148        isolate, NewTypeError(MessageTemplate::kNotCallable, run_under_lock));
 
  152  std::optional<base::TimeDelta> timeout;
 
  155        isolate, NewTypeError(MessageTemplate::kIsNotNumber, timeout_obj,
 
  158  timeout = GetTimeoutDelta(timeout_obj);
 
  164  if (!isolate->allow_atomics_wait() || js_mutex->IsCurrentThreadOwner()) {
 
  166        isolate, NewTypeError(MessageTemplate::kAtomicsOperationNotAllowed,
 
  167                              isolate->factory()->NewStringFromAsciiChecked(
 
  177          isolate, callback_result,
 
  179                          isolate->factory()->undefined_value(), {}));
 
  182      callback_result = isolate->factory()->undefined_value();
 
 
  193  constexpr char method_name[] = 
"Atomics.Mutex.lockAsync";
 
  197  if (!IsJSAtomicsMutex(*js_mutex_obj)) {
 
  199        isolate, NewTypeError(MessageTemplate::kMethodInvokedOnWrongType,
 
  200                              isolate->factory()->NewStringFromAsciiChecked(
 
  205  if (!IsCallable(*run_under_lock)) {
 
  207        isolate, NewTypeError(MessageTemplate::kNotCallable, run_under_lock));
 
  211  std::optional<base::TimeDelta> timeout = std::nullopt;
 
  212  if (!IsUndefined(*timeout_obj, isolate)) {
 
  215          isolate, NewTypeError(MessageTemplate::kIsNotNumber, timeout_obj,
 
  218    timeout = GetTimeoutDelta(timeout_obj);
 
  223      isolate, result_promise,
 
  227  return *result_promise;
 
 
  230BUILTIN(AtomicsMutexAsyncUnlockResolveHandler) {
 
  236      UnlockAsyncLockedMutexFromPromiseHandler(isolate);
 
  242  return *isolate->factory()->undefined_value();
 
 
  245BUILTIN(AtomicsMutexAsyncUnlockRejectHandler) {
 
  251      UnlockAsyncLockedMutexFromPromiseHandler(isolate);
 
  255  return *isolate->factory()->undefined_value();
 
 
  261  return *isolate->factory()->NewJSAtomicsCondition();
 
 
  266  constexpr char method_name[] = 
"Atomics.Condition.wait";
 
  272  if (!IsJSAtomicsCondition(*js_condition_obj) ||
 
  273      !IsJSAtomicsMutex(*js_mutex_obj)) {
 
  275        isolate, NewTypeError(MessageTemplate::kMethodInvokedOnWrongType,
 
  276                              isolate->factory()->NewStringFromAsciiChecked(
 
  280  std::optional<base::TimeDelta> timeout = std::nullopt;
 
  281  if (!IsUndefined(*timeout_obj, isolate)) {
 
  284          isolate, NewTypeError(MessageTemplate::kIsNotNumber, timeout_obj,
 
  287    timeout = GetTimeoutDelta(timeout_obj);
 
  290  if (!isolate->allow_atomics_wait()) {
 
  292        isolate, NewTypeError(MessageTemplate::kAtomicsOperationNotAllowed,
 
  293                              isolate->factory()->NewStringFromAsciiChecked(
 
  300  if (!js_mutex->IsCurrentThreadOwner()) {
 
  303        NewTypeError(MessageTemplate::kAtomicsMutexNotOwnedByCurrentThread));
 
  306  return isolate->heap()->ToBoolean(
 
 
  312  constexpr char method_name[] = 
"Atomics.Condition.notify";
 
  317  if (!IsJSAtomicsCondition(*js_condition_obj)) {
 
  319        isolate, NewTypeError(MessageTemplate::kMethodInvokedOnWrongType,
 
  320                              isolate->factory()->NewStringFromAsciiChecked(
 
  325  if (IsUndefined(*count_obj, isolate)) {
 
  331    if (count_double <= 0) {
 
  336    count = 
static_cast<uint32_t
>(count_double);
 
  340  return *isolate->factory()->NewNumberFromUint(
 
 
  346  constexpr char method_name[] = 
"Atomics.Condition.waitAsync";
 
  351  if (!IsJSAtomicsCondition(*js_condition_obj) ||
 
  352      !IsJSAtomicsMutex(*js_mutex_obj)) {
 
  354        isolate, NewTypeError(MessageTemplate::kMethodInvokedOnWrongType,
 
  355                              isolate->factory()->NewStringFromAsciiChecked(
 
  360  std::optional<base::TimeDelta> timeout = std::nullopt;
 
  361  if (!IsUndefined(*timeout_obj, isolate)) {
 
  364          isolate, NewTypeError(MessageTemplate::kIsNotNumber, timeout_obj,
 
  367    timeout = GetTimeoutDelta(timeout_obj);
 
  374  if (!js_mutex->IsCurrentThreadOwner()) {
 
  377        NewTypeError(MessageTemplate::kAtomicsMutexNotOwnedByCurrentThread));
 
  382      isolate, result_promise,
 
  384  return *result_promise;
 
 
  397  return *lock_promise;
 
 
static constexpr TimeDelta FromMilliseconds(int64_t milliseconds)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > Call(Isolate *isolate, DirectHandle< Object > callable, DirectHandle< Object > receiver, base::Vector< const DirectHandle< Object > > args)
static V8_EXPORT_PRIVATE MaybeDirectHandle< JSReceiver > WaitAsync(Isolate *requester, DirectHandle< JSAtomicsCondition > cv, DirectHandle< JSAtomicsMutex > mutex, std::optional< base::TimeDelta > timeout)
static constexpr uint32_t kAllWaiters
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 DirectHandle< JSObject > CreateResultObject(Isolate *isolate, DirectHandle< Object > value, bool success)
@ kUnlockedPromiseAsyncContextSlot
@ kAsyncLockedWaiterAsyncContextSlot
static MaybeDirectHandle< JSPromise > LockOrEnqueuePromise(Isolate *isolate, DirectHandle< JSAtomicsMutex > mutex, DirectHandle< Object > callback, std::optional< base::TimeDelta > timeout)
static Handle< Object > Reject(DirectHandle< JSPromise > promise, DirectHandle< Object > reason, bool debug_event=true)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > Resolve(DirectHandle< JSPromise > promise, DirectHandle< Object > resolution)
static Handle< String > TypeOf(Isolate *isolate, DirectHandle< Object > object)
static double NumberValue(Tagged< Number > obj)
static V8_WARN_UNUSED_RESULT Maybe< double > IntegerValue(Isolate *isolate, HandleType< T > input)
static constexpr Tagged< Smi > zero()
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
#define MAYBE_ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
base::Vector< const DirectHandle< Object > > args
ZoneVector< RpoNumber > & result
bool IsNumber(Tagged< Object > obj)
V8_EXPORT_PRIVATE FlagValues v8_flags
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
#define DCHECK(condition)
#define V8_LIKELY(condition)