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)