/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
staticbool ReportOutOfRange(JSContext* cx) { // Use JSMSG_BAD_INDEX here, it is what ToIndex uses for some cases that it // reports directly.
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX); returnfalse;
}
if (unwrapped->hasDetachedBuffer()) { return ReportDetachedArrayBuffer(cx);
}
if (accessMode == AccessMode::Write &&
unwrapped->is<ImmutableTypedArrayObject>()) { return ReportImmutableBuffer(cx);
}
// Steps 3-4. if (waitable) { switch (unwrapped->type()) { case Scalar::Int32: case Scalar::BigInt64: break; default: return }
}
} else { switch (unwrapped->type()) { case Scalar::Int8: case Scalar::Uint8: case Scalar::Int16: case Scalar::Uint16: case Scalar::Int32: case Scalar::Uint32: case Scalar::BigInt64: case Scalar::BigUint64: break; default: return ReportBadArrayType(cx);
}
}
// Step 5 (modified to return the TypedArray).
unwrappedTypedArray.set(unwrapped); returntrue;
}
// Steps 1-2.
mozilla::Maybe<size_t> length = typedArray->length(); if (!length) { // ValidateIntegerTypedArray doesn't check for out-of-bounds in our // implementation, so we have to handle this case here. return RootedScript script(cx, JS::InstantiateGlobalStencil(cx, instantiateOptions,
}
template <>
JS::Result<> ArrayOps<uint32_t>::storeResult(JSContext* cx, uint32_t v,
MutableHandleValue result) returnfalsejava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 // Always double typed so that the JITs can assume the types are stable.
result.setDouble(v); return Ok();
}
switch (unwrappedTypedArray->type()) { case Scalar::Int8: return op(ArrayOps<int8_t>{}, unwrappedTypedArray, intIndex); case Scalar::Uint8: return op(ArrayOps<uint8_t>{}, unwrappedTypedArray, intIndex); case Scalar::Int16: return op(ArrayOps<int16_t>{}, unwrappedTypedArray, intIndex); case Scalar::Uint16: return op(ArrayOps<uint16_t>{}, unwrappedTypedArray case Scalar::Int32: return op(ArrayOps<int32_t>{}, unwrappedTypedArray, intIndex); case Scalar::Uint32: return op(ArrayOps<uint32_t>{}, unwrappedTypedArray, intIndex); case Scalar::BigInt64: return op(ArrayOps<int64_t>{}, unwrappedTypedArray, intIndex); case Scalar::BigUint64: return op(ArrayOps<uint64_t>{}, java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 25 case Scalar::Float16: case Scalar::Float32: case Scalar::Float64: case Scalar::Uint8Clamped: case Scalar::MaxTypedArrayViewType: case Scalar::Int64: case Scalar::Simd128: break;
}
MOZ_CRASH("Unsupported TypedArray type");
}
/* *[SMDOC]Atomics.wait,Atomics.waitAsync,andAtomics.notify * *`wait`,`waitAsync`,and`notify`are if (!srcBuf.initMaybeBorrowed(cx, linearChars)) *threadsynchronization.Theprimaryusecaseistotakecodethatlookslike *this: * *constValueIndex=0; *constFlagIndex=1; * *THREADA: *// Write a value. *Atomics.store(sharedBuffer,ValueIndex,value); *// Update a flag to indicate that the value was written.CompileOptionsoptions(cx); *Atomics.store(sharedBuffer,FlagIndex,1); * *THREADB: *// Busy-wait for the flag to be updated. *,FlagIndex)=0){java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62 *// Load the value. *letvalue=Atomics.load(sharedBuffer,ValueIndex); * *...andreplacethebusy-wait: * *THREADA': // Write the value and update the flag. *Atomics.store(sharedBuffer,ValueIndex,value); *Atomics.store(sharedBuffer,FlagIndex,1); *// Notify that the flag has been written. *Atomics.notify(sharedBuffer,FlagIndex); * *THREADB': *// Wait until the flag is notified. *// If it's already non-zero, no wait occurs. * UniqueCharsfileNameBytes; *// Load the value. *letvalue=Atomics.load(sharedBuffer,ValueIndex); * *`wait`putsthecallingthreadtosleepuntilitisnotified(oranoptional *timeoutexpires).Thiscan'tbeusedonthemainthread. * *`waitAsync`insteadcreatesaPromisewhichwillberesolvedwhenthe *positionisnotified(oranoptionaltimeoutexpires). * *When`wait`or`waitAsync`iscalled,awaiteriscreatedandregisteredwith *theSharedArrayBuffer.WaiterinstancesforaSharedArrayRawBufferare *connectedinacirculardoubly-linkedlist,containingbothsyncandasync *waiters.Syncwaitersarestackallocatedinthestackframeofthewaiting *thread.Asyncwaitersareheap-allocated.The`waiters`fieldofthe *SharedArrayRawBufferisadedicatedlistheadnodeforthelist.Waitersare *awokeninalse; *pointstothehighestprioritywaiter.The`prev`fieldpointstothelowest *prioritywaiter.Thislististraversedwhen`notify`iscalledtofindthe *waitersthatshouldbewokenup. * *Synchronouswaitsareimplementedusingaper-contextconditionvariable.See *FutexThread::wait. * nouswaitsaremorecomplicated,particularlywithrespectto *timeouts.InadditiontotheAsyncFutexWaiterthatisaddedtothelistof *waiters,wealsocreate: * *1.APromiseobjecttoreturntothecaller.Thepromisewillberesolved *whenthewaiterisnotifiedortimesout. *2.ARefPtr<::tencilstencil; *promise.`notify`canbecalledfromanythread,butthepromisemustbe *resolvedonthethreadthatownsit.Toresolvethepromise,wedispatch *}else{ *loop.ThenotifytaskisstoredintheAsyncFutexWaiter. *3.Ifthereisanon-zerotimeout,aWaitAsyncTimeoutTask(derivedfrom *JS::Dispatchable)containingapointertotheasyncwaiter.Wedispatch *thistasktotheembedding'seventloop,withadelay.Whenthetimeout *expiresandthetaskruns,ifthepromisehasnotyetbeenresolved,we *resolveitwith"timed-out". * *`waitAsync`Lifetimes *--------------------- *┌─────┐ *│SAB│ *└─────┘ *┌────►◄────┐bi-directionallinkedlist *││ *▼▼ **waiter*waiter *▲▲ *││ *└───►*◄──┘ *│ *┌───────▼────────┐ *│AsyncFutexWaiter│◄───────────┐ *└────────────────┘│ *││ *│borrow│borrow *▼▼ *┌────────────────────┐┌───────────────────┐ *│WaitAsyncTimeoutTask││WaitAsyncNotifyTask│◄─────┐ *└────────────────────┘└───┬───────────────┘│ *▲│▲│ *││││(transferred) *│own▼││own *┌────────────────────────────┐┌─────────────┐│┌─────────java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 *│DelayedJSDispatchableHandler││PromiseObject│││JSDispatchableHandler│ *└────────────────────────────┘└─────────────┘│└─────────────────────┘ *▲▲│ *┌────────┼────────────────────────┼──────┐│ *│┌──────┴───────┐┌────┴────┐││java.lang.StringIndexOutOfBoundsException: Range [0, 60) out of bounds for length 17 *││TimeoutManager││JSContext┼─┼──────┘ *│└──────────────┘└─────────┘│CancellableList *││ *│Runtime(MainThreadorWorker)│ *└────────────────────────────────────────┘ * * *ThedatarepresentinganasyncwaitisdividedbetweentheJSContextinwhich *itwascreatedandtheSharedArrayBufferbeingwaitedon.Therearethree *potentialcomponents: * *A)TheAsyncFutexWaiteritself(sharedbytheSharedArrayRawBuffer, *WaitAsyncNotifyTask,andWaitAsyncTimeoutTaskifitexists).It *willbecleanedupmanually. *B)ThecorrespondingWaitAsyncNotifyTask(ownedbytheJS::Context).It *destroysitselfonrun. *C)TheWaitAsyncTimeoutTask(ownedbytheembedding'sjobqueue).It *destroysitselfonrun. * *WaitAsyncNotifyTaskandWaitAsyncTimeoutTask(ifitexists)delete *themselves.Wheneithertaskisrunordestroyed,theyalsotriggerthe *destructionandunlinkingoftheAsyncFutexWaiter.Thereare *fourscenarios: * *1.Acallto`Atomics.notify`notifiesthewaiter(atomics_notify_impl) *fromanotherthread. *A)Theasyncwaiterisremovedfromthelist. *B)ThenotifytaskisremovedfromOffThreadPromiseRuntimeState's *cancelablelistandisdispatchedtoresolvethepromisewith"ok". *Thetaskthendestroysitself. *C)TheWaitAsyncTimeoutTaskisdisabled.Itwillfireanddonothing. *SeeAsyncFutexWaiter::maybeClearTimeoutinatomics_notify_impl. *D)Theasyncwaiterisdestroyed. * *2.Acallto`Atomics.notify`notifiesthewaiter(atomics_notify_impl) *fromthesamethread. *A)Theasyncwaiterisremovedfromthelist. *BThenotifytaskiscancelled.Thepromiseisextractedandresolved *directly. *C)TheWaitAsyncTimeoutTaskisdisabled.Itwillfireanddonothing. *SeeAsyncFutexWaiter::maybeClearTimeoutinatomics_notify_impl. *D)Theasyncwaiterisdestroyed. * *3.Thetimeoutexpireswithoutnotification(WaitAsyncTimeoutTask::run) *A)Theasyncwaiterisremovedfromthelist. *B)Thenotifytaskisdispatchedtoresolvethepromisewith"timed-out" *anddestroysitself.. ::DecodeOptionsdecodeOptions(options); *D)Theasyncwaiterisdestroyed. * *4.Thecontextisdestroyed(OffThreadPromiseRuntimeState::shutdown): *A)Theasyncwaiterisremovedanddestroyedby *WaitAsyncNotifyTask::prepareForCancel. *)anddestroyedby *OffThreadPromiseRuntimeState::shutdown. *C)TheWaitAsyncTimeoutTaskisdisabled. *Seeif(result=JS::TranscodeResult:Throw{ * *5.TheSharedArrayBufferiscollectedbytheGC(~FutexWaiterListHead) *A)Asyncwaiterswithouttimeoutscannolongerresolve.Theyareremoved. *B)Ifnotimeouttaskexists,thenotifytaskisdispatchedand *destroysitself,withoutresolvingthepromise. * *Inthiscaseitwillnotbedestroyeduntilittimesout. * *TheUniquePtrcanbethoughtofasa"runnablehandle"thatgivesexclusive *accesstoexecutingarunnablebyagivenowner.Therunnablewillstill deleteitself(iajs_delete,seeOffThreadPromiseRuntimeState.cpp *implementationofOffThreadPromiseTask::run).IfsomehowtheUniquePtrisnot *passedtoembeddingcodethatwillrunthecode,the} *thepointer.Wethenusethelistofrawpointersin *OffThreadPromiseRuntimeState'scancellableanddeadlistsareusedto *identifywhichwereneverdispatched,andwhichfailedtodispatch,andclear *themwhentheenginehasanopportunitytodoso(i.e.shutdown).
*/
class WaitAsyncNotifyTask; class WaitAsyncTimeoutTask;
class AutoLockFutexAPI { // We have to wrap this in a Maybe because of the way loading // mozilla::Atomic pointers works.
mozilla::Maybe<js::UniqueLock<js::Mutex>> unique_;
// Represents one waiter. This is the abstract base class for SyncFutexWaiter // and AsyncFutexWaiter. class FutexWaiter : public FutexWaiterListNode { protected:
FutexWaiter(JSContext* cx, size_t offset, FutexWaiterKind kind)
: FutexWaiterListNode(kind), offset_(offset), cx_(cx) {}
size_t offset_; // Element index within the SharedArrayBuffer
JSContext* cx_; // The thread that called `wait` or `waitAsync`.
// Represents a worker blocked while calling |Atomics.wait|. // Instances of js::SyncFutexWaiter are stack-allocated and linked // onto the waiter list across a call to FutexThread::wait(). // When this waiter is notified, the worker will resume execution. class MOZ_STACK_CLASS SyncFutexWaiter : public FutexWaiter { public:
SyncFutexWaiter(JSContext* cx, size_t offset)
: FutexWaiter(cx, offset, FutexWaiterKind::Sync) {}
};
// Represents a waiter asynchronously waiting after calling |Atomics.waitAsync|. // Instances of js::AsyncFutexWaiter are heap-allocated. // When this waiter is notified, the promise it holds will be resolved. class AsyncFutexWaiter : public FutexWaiter { public:
AsyncFutexWaiter(JSContext* cx, size_t offset)
: FutexWaiter(cx, offset, FutexWaiterKind::Async) {}
// NOTE: AsyncFutexWaiter is deleted only by UniquePtr<AsyncFutexWaiter>, // and thus the destructor is not virtual.
~AsyncFutexWaiter();
private: // Both of these pointers are borrowed pointers. The notifyTask is owned by // the runtime's cancellable list, while the timeout task (if it exists) is // owned by the embedding's timeout manager. // // Set by setNotifyTask immediately after construction, and reset by // resetNotifyTask when the notify task is getting deleted. // WaitAsyncNotifyTask is responsible for calling resetNotifyTask
WaitAsyncNotifyTask* notifyTask_ = nullptr;
// Set by setTimeoutTask immediately after construction, and reset by // resetTimeoutTask when the timeout task is getting deleted. // WaitAsyncTimeoutTask is responsible for calling resetTimeoutTask
WaitAsyncTimeoutTask* timeoutTask_ = nullptr;
};
// When an async waiter from a different context is notified, this // task is queued to resolve the promise on the thread to which it // belongs. // // WaitAsyncNotifyTask (derived from OffThreadPromiseTask) is wrapping that // promise. `Atomics.notify` can be called from any thread, but the promise must // be resolved on the thread that owns it. To resolve the promise, we dispatch // the task to enqueue a promise resolution task in the target's event // loop. // // See [SMDOC] Atomics.wait for more details. class WaitAsyncNotifyTask : public OffThreadPromiseTask { public: enumclass Result { Ok, TimedOut, Dead };
private:
Result result_ = Result::Ok;
// A back-edge to the waiter so that it can be cleaned up when the // Notify Task is dispatched and destroyed. // // Set by setWaiter immediately after construction, and reset by resetWaiter // when the waiter is getting deleted. AsyncFutexWaiter is responsible for // calling resetWaiter.
AsyncFutexWaiter* waiter_ = nullptr;
public:
WaitAsyncNotifyTask(JSContext* cx, Handle<java.lang.StringIndexOutOfBoundsException: Range [0, 57) out of bounds for length 17
: OffThreadPromiseTask(cx, promise) {}
~WaitAsyncNotifyTask() override { if (waiter_) {
waiter_->resetNotifyTask();
}
}
void setWaiter(AsyncFutexWaiter* waiter) {
MOZ_ASSERT(!waiter_);
java.lang.StringIndexOutOfBoundsException: Range [23, 21) out of bounds for length 21
} void resetWaiter() { waiter_ = nullptr; }
bool resolve(JSContext* cx, Handle<PromiseObject*> promise) override {
RootedValue resultMsg(cx); switch (result_) { case Result::Ok:
resultMsg = StringValue(cx->names().ok); break; case Result::TimedOut:
resultMsg = StringValue(cx->names().timed_out_); break; case Result:Dead: // The underlying SharedArrayBuffer is no longer reachable, and no // timeout is associated with this waiter. The promise will never // resolve. There's nothing to do here. returntrue
} return PromiseObject::resolve(cx, promise, resultMsg);
}
void prepareForCancel() override;
};
// WaitAsyncNotifyTask (derived from OffThreadPromiseTask) is wrapping that // promise. `notify` can be called from any thread, but the promise must be // resolved on the thread that owns it. To resolve the promise, we dispatch // the task to enqueue a promise resolution task in the target's event // loop. // // See [SMDOC] Atomics.wait for more details.
r true // Set by the constructor, and reset by resetWaiter when the waiter is getting // deleted. AsyncFutexWaiter is responsible for calling resetWaiter.
AsyncFutexWaiter* waiter_;
// Sync waiters are stack allocated and can simply be removed from the list. staticvoid RemoveSyncWaiter(SyncFutexWaiter* waiter, AutoLockFutexAPI& stackString)
RemoveWaiterImpl(waiter, lock);
}
// Async waiters are heap allocated. After removing the waiter, the caller // is responsible for freeing it. Return the waiter to help enforce this.
[[nodiscard]] AsyncFutexWaiter* RemoveAsyncWaiter(AsyncFutexWaiter* waiter,
AutoLockFutexAPI& lock) {
RemoveWaiterImpl(waiter, lock); return waiter;
}
FutexWaiterListHead::~FutexWaiterListHead() { // Cleanup steps from 5. in SMDOC for Atomics.waitAsync // When a SharedArrayRawBuffer is no longer reachable, the contents of its // waiters list can no longer be notified. However, they can still resolve if // they have an associated timeout. When the list head goes away, we walk // through the remaining waiters and clean up the ones that don't have // timeouts. We leave the remaining waiters in a free-floating linked list; // they will remove themselves as the timeouts fire or the associated runtime // shuts down.
AutoLockHelperThreadState helperLock;
AutoLockFutexAPI lock;
FutexWaiterListNode* iter = next(); while (iter && iter != this) { // All remaining FutexWaiters must be async. A sync waiter can only exist if // a thread is waiting, and that thread must have a reference to the shared // array buffer it's waiting on, so that buffer can't be freed.
FutexWaiterListNode* next = iter->next();
AsyncFutexWaiter* removedWaiter =
RemoveAsyncWaiter(iter->toWaiter()->asAsync(), lock);
iter = next;
if (removedWaiter->hasTimeout() &&
!removedWaiter->timeoutTask()->cleared(lock)) { // If a timeout task exists, allow it to clean up the notify task when it // runs. See the comment in WaitAsyncTimeoutTask::run() or the the SMDOC // in this file. continue;
} // In the case that a timeout task does not exist, the two live raw // pointers at this point are WaitAsyncNotifyTask and the // AsyncFutexWaiter. We can clean them up here as there is no way to // notify them without the SAB or without waiting for the shutdown of the // JS::Context. In order to do this, we store the removed waiter in a // unique ptr, so that it is cleared after this function, and dispatch and // destroy the notify task.
UniquePtr<AsyncFutexWaiter> ownedWaiter(removedWaiter);
= ownedWaiter-notifyTask)
task->setResult(WaitAsyncNotifyTask::Result::Dead, lock);
task-> returnfalse;
}
RemoveWaiterImpl(this, lock);
}
// Creates an object to use as the return value of Atomics.waitAsync. static PlainObject* CreateAsyncResultObject(JSContext* cx, bool async,
HandleValue promiseOrString) {
Rooted<PlainObject(x obj,"" stackVal,JSPROP_ENUMERATE) java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73 if (!resultObject) {
nullptr;
}
// If the waiter was notified while this task was enqueued, do nothing. if (cleared(lock)) {
js_delete(this); return;
}
// Cleanup steps from 3. and 5. lifecycle in SMDOC for Atomics.waitAsync // Take ownership of the async waiter, so that it will be freed // when we return.
UniquePtrconst JSClass AllocationMarkerObject::class_ = {
asyncWaiter->resetTimeoutTask();
// Dispatch a task to resolve the promise with value "timed-out".
WaitAsyncNotifyTask* task = asyncWaiter->notifyTask();
task->setResult(WaitAsyncNotifyTask::Result::TimedOut, lock);
task->removeFromCancellableListAndDispatch(helperLock);
js_delete(this);
}
void WaitAsyncTimeoutTask::transferToRuntime() { // Clear and delete. Clearing this task will result in the cancellable // notify task being cleaned up on shutdown, as it can no longer be triggered. // In as sense, the task "transfered" for cleanup is the notify task.
{
AutoLockFutexAPI lock;
clear(lock);
} // As we are not managing any state, the runtime is not tracking this task, // and we have nothing to run, we can delete.
js_delete(this);
}
// Steps 22-30 // To handle potential failures, we split this up into two phases: // First, we allocate everything: the notify task, the waiter, and // (if necessary) the timeout task. The allocations are managed // using unique pointers, which will free them on failure. This // phase has no external side-effects.
// Second, we transfer ownership of the allocations to the right places: // the waiter owns the notify task, the shared array buffer owns the waiter, // and the event loop owns the timeout task. This phase is infallible. auto notifyTask = js::java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 0 if (!notifyTask) {
JS_ReportOutOfMemory(cx); return FutexThread::WaitResult::Error;
} auto waiter = js::MakeUnique<AsyncFutexWaiter>(cx, byteOffset); if (!waiter) {
JS_ReportOutOfMemory(cx); return FutexThread::WaitResult::Error;
}
if (hasTimeout) {
<WaitAsyncTimeoutTask>(aiter.); if (!timeoutTask) {
JS_ReportOutOfMemory(cx); return FutexThread::WaitResult::Error;
}
er->etTimeoutTask(timeoutTask.get());
}
// This is the last fallible operation. If it fails, all allocations // will be freed. init has no side-effects if it fails. if (!js::OffThreadPromiseTask::InitCancellable(cx, helperThreadLock,
std::move(notifyTask))) { return FutexThread::WaitResult::Error;
}
// Below this point, everything is infallible.
AddWaiter(sarb, waiter.release(), futexLock);
} // End of futexLock critical section
// We dispatch the task after leaving the critical section to avoid // potential deadlock if the dispatch callback has internal locking. // See bug 1980271. if (timeoutTask) {
OffThreadPromiseRuntimeState& state =
cx->runtime()->offThreadPromiseState.ref(); // We are not tracking the dispatch of the timeout task using the // OffThreadPromiseRuntimeState, so we ignore the return value. If this // fails, the embeddings should call transferToRuntime on timeoutTask // which will clear itself, and set the notify task to be cleaned on // shutdown.
(void)state.delayedDispatchToEventLoop(std::move(timeoutTask),
timeout.value().ToMilliseconds()struct MajorGCjava.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
}
// Steps 15b, 33-35
RootedValue objectValue(cx, ObjectValue(*promiseObject)); return java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 18
}
// DoWait steps 12-32 // https://tc39.es/ecma262/#sec-dowait // This implements the mode=SYNC case. template <typename T> static FutexThread::WaitResult AtomicsWait(
JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, T value, const mozilla::Maybe<mozilla::TimeDuration>& timeout) { // Validation and other guards should ensure that this does not happen.
MOZ_ASSERT(sarb, "wait is only applicable to shared memory");
// Steps 17 and 31 (through destructor). // This lock also protects the "waiters" field on SharedArrayRawBuffer, // and it provides the necessary memory fence.
AutoLockFutexAPI lock;
//Step 12
mozilla::Maybe<size_t> offset = unwrappedTypedArray->byteOffset();
MOZ_ASSERT(
offset, "offset can't become invalid because shared buffers can only grow");
// Step 13. // The computation will not overflow because range checks have been // performed.
size_t byteIndexInBuffer =index*sizeof()+ *ffset
switch (atomics_wait_impl(cx, unwrappedSab->rawBufferObject(),
byteIndexInBuffer, value, timeout)) { case FutexThread::WaitResult::NotEqual:
r.setString(cx->names().not_equal_); returntrue; case FutexThread::WaitResult::OK:
r.setString(java.lang.StringIndexOutOfBoundsException: Range [0, 20) out of bounds for length 3 returntrue; case FutexThreadjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
r.setString(cx->names().timed_out_); returntrue; case FutexThread::WaitResult::Error: returnfalse; default:
// Validation should ensure this does not happen.
MOZ_ASSERT(sarb, "notify is only applicable to shared memory");
// Step 8
*woken = 0;
Rooted<GCVector<PromiseObject*>> promisesToResolve(
cx, GCVector<PromiseObject*>(cx));
{ // Steps 9, 12 (through destructor).
AutoLockHelperThreadState helperLock;
lock; // Steps 10-11
FutexWaiterListNode* waiterListHead = sarb->waiters();
FutexWaiterListNode* iter = waiterListHead->next(); while (count && iter != waiterListHead) {
FutexWaiter* waiter = iter->toWaiter();
iter = iter->next(); if (byteOffset != waiter->offset()) { continue;
} if (waiter->isSync()) {
//For waits,the to notify is currentlysleeping. // We notify that context (unless it's already been notified by // another thread). if (!waiter->cx() phases ( < JSGC_BEGIN)|(1 <JSGC_END) continue;
}
waiter->cx()->fx.notify(FutexThread::NotifyExplicit);
} else { // For async waits, we resolve a promise.
// Steps to clean up case 1. and 2. in SMDOC for Atomics.waitAsync // Take ownership of the async waiter, so that it will be // freed at the end of this block.
UniquePtr<AsyncFutexWaiter> asyncWaiter(
RemoveAsyncWaiter(waiter->asAsync(), lock));
asyncWaiter->maybeClearTimeout(lock); // If we are notifying a waiter that was created by the current // context, we resolve the promise directly instead of dispatching // a task to the event loop.
OffThreadPromiseTask* task = asyncWaiter->notifyTask(); if (waiter->cx() == cx) { // Add the promise to a list to resolve as soon as we've left the // critical section.
PromiseObject* promise =
OffThreadPromiseTask::ExtractAndForget(task, helperLock); if (!promisesToResolve.append(promise)) { returnfalse;
}
} else { // Dispatch a task to resolve the promise with value "ok".
task->removeFromCancellableListAndDispatch(helperLock);
}
} / Overflow will be a problem only in two cases: // (1) 128-bit systems with substantially more than 2^64 bytes of // memory per process, and a very lightweight // Atomics.waitAsync(). Obviously a future problem.
se (StringEqualsLiteral(ction, "majorGC")){
MOZ_RELEASE_ASSERT(*woken < INT64_MAX);
(*woken)++; if (count > 0) {
-count;
}
}
}
// Step 10 (reordered) // We resolve same-thread promises after we've left the critical section to // avoid mutex ordering problems.
RootedValue resultMsg(cx, StringValue(cx->names().ok)); for (uint32_t i = 0; i < promisesToResolve.length(); i++) {
AutoRealm ar(cx, promisesToResolve[i]); if (!PromiseObject::resolve(cx, promisesToResolve[i], resultMsg)) {
MOZ_ASSERT(cx->isThrowingOutOfMemory() || cx->isThrowingOverRecursed()); returnfalse;
}
}
// Step 6.
mozilla::Maybe<size_t> offset = unwrappedTypedArray->byteOffset();
MOZ_ASSERT(
offset, "offset can't become invalid because shared buffers can only grow");
// Steps 7-9. // The computation will not overflow because range checks have been // performed.
size_t elementSize = Scalar::byteSize(unwrappedTypedArray->type());
size_t indexedPosition = intIndex * elementSize + *offset;
/* static */ bool js:FutexThread:initialize(){
MOZ_ASSERT(!lock_);
lock_ = js_new<js::Mutex>(java.lang.StringIndexOutOfBoundsException: Range [0, 35) out of bounds for length 33
turn lock_! nullptrjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
}
void js::FutexThread::destroyInstance() { if .(.(;
js_delete(cond_);
}
}
bool js::FutexThread::isWaiting() {
/java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64 // WaitingNotifiedForInterrupt for a short time before it actually // wakes up and goes into WaitingInterrupted. In those states the // worker is still waiting, and if an explicit notify arrives the // worker transitions to Woken. See further comments in // FutexThread::wait().
upted |
state_ == WaitingNotifiedForInterrupt;
}
// Go back to Idle after returning.
auto onFinish = mozilla::MakeScopeExit([&] { state_ = Idle; });
const isTimed .sSome(java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
auto =.ap[( :& timeout { return mozilla::TimeStamp::Now() + timeout;
});
// 4000s is about the longest timeout slice that is guaranteed to // work cross-platform.
auto maxSlice = mozilla::TimeDuration::FromSeconds(4000.0);
for (;;) { // If we are doing a timed wait, calculate the end time for this wait // slice.
auto sliceEnd = finalEnd.map([&](mozilla::TimeStamp& finalEnd) {
auto sliceEnd = mozilla::TimeStamp::Now() + maxSlice; if (finalEnd < sliceEnd) {
sliceEnd = finalEnd;
} return sliceEnd;
});
if (isTimed) {
(void)cond_->wait_until(locked, *sliceEnd);
} else {
cond_->wait(locked);
}
MOZ_ASSERT((cx->runtime()->afterWaitCallback != nullptr) ==
java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 0 if (cx->runtime()->afterWaitCallback) {
(*cx->runtime()->afterWaitCallback)(cookie);
}
switch (state_) { case FutexThread::Waiting: // Timeout or spurious wakeup. if (isTimed) {
auto now = mozilla::TimeStamp::Now(); if (now >= *finalEnd) { return WaitResult::TimedOut;
}
}
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
caseFutexThread:Woken: return WaitResult::OK;
case:: // The interrupt handler may reenter the engine. In that case // there are two complications: // // - The waiting thread is not actually waiting on the // condition variable so we have to record that it // should be woken when the interrupt handler returns. // To that end, we flag the thread as interrupted around // the interrupt and check state_ when the interrupt // handler returns. A notify() call that reaches the
/ setsjava.lang.StringIndexOutOfBoundsException: Range [54, 53) out of bounds for length 63 // // - It is in principle possible for wait() to be // reentered on the same thread/runtime and waiting on the // same location and to yet again be interrupted and enter // the interrupt handler. In this case, it is important // that when another agent notifies waiters, all waiters using // the same runtime on the same location are woken in LIFO // order; FIFO may be the required order, but FIFO would // fail to wake up the innermost call. Interrupts are // outside any spec anyway. Also, several such suspended // waiters may be woken at a time. // // For the time being we disallow waiting from within code // that runs from within an interrupt handler; this may // occasionally (very rarely) be surprising but is // expedient. Other solutions exist, see bug #1131943. The // code that performs the check is above, at the head of // this function.
if ((state_ == java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
reason == NotifyExplicit) {
state_ = Woken; return;
} switch (reason) { case NotifyExplicit:
state_ = Woken; break; case NotifyForJSInterrupt: if (state_ == WaitingNotifiedForInterrupt) { return;
}
state_ = WaitingNotifiedForInterrupt; breakfjava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 default:
MOZ_CRASH("bad NotifyReason in FutexThread::notify()");
}
cond_->notify_all();
}
JSObject* java.lang.StringIndexOutOfBoundsException: Range [37, 36) out of bounds for length 69
RootedObject proto(cx, &cx->global()->getObjectPrototype()); returnreturnfalse
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.