Skip to content

Commit

Permalink
Normative: Allow Atomics methods to work on ArrayBuffers.
Browse files Browse the repository at this point in the history
Allow Atomics methods to work on ArrayBuffers in a fully deterministic
fashion. Atomics.wait still throws when used on ArrayBuffers, while
Atomics.notify always returns 0.
  • Loading branch information
syg committed Mar 25, 2020
1 parent 6fa3b1a commit 67e63a5
Showing 1 changed file with 23 additions and 19 deletions.
42 changes: 23 additions & 19 deletions spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -36957,23 +36957,26 @@ <h1>SetValueInBuffer ( _arrayBuffer_, _byteIndex_, _type_, _value_, _isTypedArra

<emu-clause id="sec-getmodifysetvalueinbuffer" aoid="GetModifySetValueInBuffer">
<h1>GetModifySetValueInBuffer ( _arrayBuffer_, _byteIndex_, _type_, _value_, _op_ [ , _isLittleEndian_ ] )</h1>
<p>The abstract operation GetModifySetValueInBuffer takes six parameters, a SharedArrayBuffer _arrayBuffer_, a nonnegative integer _byteIndex_, a TypedArray element type _type_, a Number or BigInt _value_, a read-modify-write modification function _op_, and optionally a Boolean _isLittleEndian_. This operation performs the following steps:</p>
<p>The abstract operation GetModifySetValueInBuffer takes six parameters, an ArrayBuffer or SharedArrayBuffer _arrayBuffer_, a nonnegative integer _byteIndex_, a TypedArray element type _type_, a Number or BigInt _value_, a read-modify-write modification function _op_, and optionally a Boolean _isLittleEndian_. This operation performs the following steps:</p>
<emu-alg>
1. Assert: IsSharedArrayBuffer(_arrayBuffer_) is *true*.
1. Assert: There are sufficient bytes in _arrayBuffer_ starting at _byteIndex_ to represent a value of _type_.
1. Assert: ! IsNonNegativeInteger(_byteIndex_) is *true*.
1. Assert: Type(_value_) is BigInt if ! IsBigIntElementType(_type_) is *true*; otherwise, Type(_value_) is Number.
1. Let _block_ be _arrayBuffer_.[[ArrayBufferData]].
1. Let _elementSize_ be the Element Size value specified in <emu-xref href="#table-the-typedarray-constructors"></emu-xref> for Element Type _type_.
1. If _isLittleEndian_ is not present, set _isLittleEndian_ to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
1. Let _rawBytes_ be NumericToRawBytes(_type_, _value_, _isLittleEndian_).
1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
1. Let _eventList_ be the [[EventList]] field of the element in _execution_.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
1. Let _rawBytesRead_ be a List of length _elementSize_ of nondeterministically chosen byte values.
1. NOTE: In implementations, _rawBytesRead_ is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
1. Let _rmwEvent_ be ReadModifyWriteSharedMemory { [[Order]]: ~SeqCst~, [[NoTear]]: *true*, [[Block]]: _block_, [[ByteIndex]]: _byteIndex_, [[ElementSize]]: _elementSize_, [[Payload]]: _rawBytes_, [[ModifyOp]]: _op_ }.
1. Append _rmwEvent_ to _eventList_.
1. Append Chosen Value Record { [[Event]]: _rmwEvent_, [[ChosenValue]]: _rawBytesRead_ } to _execution_.[[ChosenValues]].
1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, then
1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
1. Let _eventList_ be the [[EventList]] field of the element in _execution_.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
1. Let _rawBytesRead_ be a List of length _elementSize_ of nondeterministically chosen byte values.
1. NOTE: In implementations, _rawBytesRead_ is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
1. Let _rmwEvent_ be ReadModifyWriteSharedMemory { [[Order]]: ~SeqCst~, [[NoTear]]: *true*, [[Block]]: _block_, [[ByteIndex]]: _byteIndex_, [[ElementSize]]: _elementSize_, [[Payload]]: _rawBytes_, [[ModifyOp]]: _op_ }.
1. Append _rmwEvent_ to _eventList_.
1. Append Chosen Value Record { [[Event]]: _rmwEvent_, [[ChosenValue]]: _rawBytesRead_ } to _execution_.[[ChosenValues]].
1. Else,
1. Let _rawBytesAtIndex_ be a List of _elementSize_ containing, in order, the _elementSize_ sequence of bytes starting with _block_[_byteIndex_].
1. Let _rawBytesRead_ be _op_(_rawBytesAtIndex_, _rawBytes_).
1. Return RawBytesToNumeric(_type_, _rawBytesRead_, _isLittleEndian_).
</emu-alg>
</emu-clause>
Expand Down Expand Up @@ -37648,9 +37651,9 @@ <h1>The Atomics Object</h1>
<emu-clause id="sec-abstract-operations-for-atomics">
<h1>Abstract Operations for Atomics</h1>

<emu-clause id="sec-validatesharedintegertypedarray" aoid="ValidateSharedIntegerTypedArray">
<h1>ValidateSharedIntegerTypedArray ( _typedArray_ [ , _waitable_ ] )</h1>
<p>The abstract operation ValidateSharedIntegerTypedArray takes one argument _typedArray_ and an optional Boolean _waitable_. It performs the following steps:</p>
<emu-clause id="sec-validateintegertypedarray" aoid="ValidateIntegerTypedArray" oldid="sec-validatesharedintegertypedarray">
<h1>ValidateIntegerTypedArray ( _typedArray_ [ , _waitable_ ] )</h1>
<p>The abstract operation ValidateIntegerTypedArray takes one argument _typedArray_ and an optional Boolean _waitable_. It performs the following steps:</p>
<emu-alg>
1. If _waitable_ is not present, set _waitable_ to *false*.
1. Perform ? RequireInternalSlot(_typedArray_, [[TypedArrayName]]).
Expand All @@ -37662,7 +37665,6 @@ <h1>ValidateSharedIntegerTypedArray ( _typedArray_ [ , _waitable_ ] )</h1>
1. If ! IsUnclampedIntegerElementType(_type_) is *false* and ! IsBigIntElementType(_type_) is *false*, throw a *TypeError* exception.
1. Assert: _typedArray_ has a [[ViewedArrayBuffer]] internal slot.
1. Let _buffer_ be _typedArray_.[[ViewedArrayBuffer]].
1. If IsSharedArrayBuffer(_buffer_) is *false*, throw a *TypeError* exception.
1. Return _buffer_.
</emu-alg>
</emu-clause>
Expand Down Expand Up @@ -37796,7 +37798,7 @@ <h1>NotifyWaiter ( _WL_, _W_ )</h1>
<h1>AtomicReadModifyWrite ( _typedArray_, _index_, _value_, _op_ )</h1>
<p>The abstract operation AtomicReadModifyWrite takes four arguments, _typedArray_, _index_, _value_, and a pure combining operation _op_. The pure combining operation _op_ takes two List of byte values arguments and returns a List of byte values. The operation atomically loads a value, combines it with another value, and stores the result of the combination. It returns the loaded value. It performs the following steps:</p>
<emu-alg>
1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_).
1. Let _buffer_ be ? ValidateIntegerTypedArray(_typedArray_).
1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1. If _typedArray_.[[ContentType]] is ~BigInt~, let _v_ be ? ToBigInt(_value_).
Expand All @@ -37813,7 +37815,7 @@ <h1>AtomicReadModifyWrite ( _typedArray_, _index_, _value_, _op_ )</h1>
<h1>AtomicLoad ( _typedArray_, _index_ )</h1>
<p>The abstract operation AtomicLoad takes two arguments, _typedArray_, _index_. The operation atomically loads a value and returns the loaded value. It performs the following steps:</p>
<emu-alg>
1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_).
1. Let _buffer_ be ? ValidateIntegerTypedArray(_typedArray_).
1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1. Let _elementSize_ be the Element Size value specified in <emu-xref href="#table-the-typedarray-constructors"></emu-xref> for _arrayTypeName_.
Expand Down Expand Up @@ -37887,7 +37889,7 @@ <h1>Atomics.and ( _typedArray_, _index_, _value_ )</h1>
<h1>Atomics.compareExchange ( _typedArray_, _index_, _expectedValue_, _replacementValue_ )</h1>
<p>The following steps are taken:</p>
<emu-alg>
1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_).
1. Let _buffer_ be ? ValidateIntegerTypedArray(_typedArray_).
1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1. If _typedArray_.[[ContentType]] is ~BigInt~, then
Expand Down Expand Up @@ -37959,7 +37961,7 @@ <h1>Atomics.or ( _typedArray_, _index_, _value_ )</h1>
<h1>Atomics.store ( _typedArray_, _index_, _value_ )</h1>
<p>The following steps are taken:</p>
<emu-alg>
1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_).
1. Let _buffer_ be ? ValidateIntegerTypedArray(_typedArray_).
1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1. If _arrayTypeName_ is *"BigUint64Array"* or *"BigInt64Array"*, let _v_ be ? ToBigInt(_value_).
Expand Down Expand Up @@ -37995,7 +37997,8 @@ <h1>Atomics.sub ( _typedArray_, _index_, _value_ )</h1>
<h1>Atomics.wait ( _typedArray_, _index_, _value_, _timeout_ )</h1>
<p>`Atomics.wait` puts the calling agent in a wait queue and puts it to sleep until it is notified or the sleep times out. The following steps are taken:</p>
<emu-alg>
1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_, *true*).
1. Let _buffer_ be ? ValidateIntegerTypedArray(_typedArray_, *true*).
1. If IsSharedArrayBuffer(_buffer_) is *false*, throw a *TypeError* exception.
1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1. If _arrayTypeName_ is *"BigInt64Array"*, let _v_ be ? ToBigInt64(_value_).
Expand Down Expand Up @@ -38031,7 +38034,7 @@ <h1>Atomics.wait ( _typedArray_, _index_, _value_, _timeout_ )</h1>
<h1>Atomics.notify ( _typedArray_, _index_, _count_ )</h1>
<p>`Atomics.notify` notifies some agents that are sleeping in the wait queue. The following steps are taken:</p>
<emu-alg>
1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_, *true*).
1. Let _buffer_ be ? ValidateIntegerTypedArray(_typedArray_, *true*).
1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1. If _count_ is *undefined*, let _c_ be *+&infin;*.
1. Else,
Expand All @@ -38042,6 +38045,7 @@ <h1>Atomics.notify ( _typedArray_, _index_, _count_ )</h1>
1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1. Let _elementSize_ be the Element Size value specified in <emu-xref href="#table-the-typedarray-constructors"></emu-xref> for _arrayTypeName_.
1. Let _indexedPosition_ be (_i_ &times; _elementSize_) + _offset_.
1. If IsSharedArrayBuffer(_buffer_) is *false*, return 0.
1. Let _WL_ be GetWaiterList(_block_, _indexedPosition_).
1. Let _n_ be 0.
1. Perform EnterCriticalSection(_WL_).
Expand Down

0 comments on commit 67e63a5

Please sign in to comment.