25.2 SharedArrayBuffer Objects
25.2.1 Fixed-length and Growable SharedArrayBuffer Objects
A fixed-length SharedArrayBuffer is a SharedArrayBuffer whose byte length cannot change after creation.
A growable SharedArrayBuffer is a SharedArrayBuffer whose byte length may increase after creation via calls to
The kind of SharedArrayBuffer object that is created depends on the arguments passed to
25.2.2 Abstract Operations for SharedArrayBuffer Objects
25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] )
The abstract operation AllocateSharedArrayBuffer takes arguments constructor (a
- Let slots be « [[ArrayBufferData]] ».
- If maxByteLength is present and maxByteLength is not
empty , let allocatingGrowableBuffer betrue ; otherwise let allocatingGrowableBuffer befalse . - If allocatingGrowableBuffer is
true , then- If byteLength > maxByteLength, throw a
RangeError exception. - Append [[ArrayBufferByteLengthData]] and [[ArrayBufferMaxByteLength]] to slots.
- If byteLength > maxByteLength, throw a
- Else,
- Append [[ArrayBufferByteLength]] to slots.
- Let obj be ?
OrdinaryCreateFromConstructor (constructor,"%SharedArrayBuffer.prototype%" , slots). - If allocatingGrowableBuffer is
true , let allocLength be maxByteLength; otherwise let allocLength be byteLength. - Let block be ?
CreateSharedByteDataBlock (allocLength). - Set obj.[[ArrayBufferData]] to block.
- If allocatingGrowableBuffer is
true , thenAssert : byteLength ≤ maxByteLength.- Let byteLengthBlock be ?
CreateSharedByteDataBlock (8). - Perform
SetValueInBuffer (byteLengthBlock, 0,biguint64 ,ℤ (byteLength),true ,seq-cst ). - Set obj.[[ArrayBufferByteLengthData]] to byteLengthBlock.
- Set obj.[[ArrayBufferMaxByteLength]] to maxByteLength.
- Else,
- Set obj.[[ArrayBufferByteLength]] to byteLength.
- Return obj.
25.2.2.2 IsSharedArrayBuffer ( obj )
The abstract operation IsSharedArrayBuffer takes argument obj (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. It tests whether an object is an ArrayBuffer, a SharedArrayBuffer, or a subtype of either. It performs the following steps when called:
- Let bufferData be obj.[[ArrayBufferData]].
- If bufferData is
null , returnfalse . - If bufferData is a
Data Block , returnfalse . Assert : bufferData is aShared Data Block .- Return
true .
25.2.2.3 HostGrowSharedArrayBuffer ( buffer, newByteLength )
The
The implementation of HostGrowSharedArrayBuffer must conform to the following requirements:
- If the abstract operation does not complete normally with
unhandled , and newByteLength < the current byte length of the buffer or newByteLength > buffer.[[ArrayBufferMaxByteLength]], throw aRangeError exception. - Let isLittleEndian be the value of the [[LittleEndian]] field of the
surrounding agent 'sAgent Record . If the abstract operation completes normally withhandled , aWriteSharedMemory orReadModifyWriteSharedMemory event whose [[Order]] isseq-cst , [[Payload]] isNumericToRawBytes (biguint64 , newByteLength, isLittleEndian), [[Block]] is buffer.[[ArrayBufferByteLengthData]], [[ByteIndex]] is 0, and [[ElementSize]] is 8 is added to thesurrounding agent 'scandidate execution such that racing calls toSharedArrayBuffer.prototype.grow
are not "lost", i.e. silently do nothing.
The second requirement above is intentionally vague about how or when the current byte length of buffer is read. Because the byte length must be updated via an atomic read-modify-write operation on the underlying hardware, architectures that use load-link/store-conditional or load-exclusive/store-exclusive instruction pairs may wish to keep the paired instructions close in the instruction stream. As such, SharedArrayBuffer.prototype.grow itself does not perform bounds checking on newByteLength before calling HostGrowSharedArrayBuffer, nor is there a requirement on when the current byte length is read.
This is in contrast with
The default implementation of HostGrowSharedArrayBuffer is to return
25.2.3 The SharedArrayBuffer Constructor
The SharedArrayBuffer
- is %SharedArrayBuffer%.
- is the initial value of the
"SharedArrayBuffer" property of theglobal object , if that property is present (see below). - creates and initializes a new SharedArrayBuffer when called as a
constructor . - is not intended to be called as a function and will throw an exception when called in that manner.
- may be used as the value of an
extends
clause of a class definition. Subclassconstructors that intend to inherit the specified SharedArrayBuffer behaviour must include asuper
call to the SharedArrayBufferconstructor to create and initialize subclass instances with the internal state necessary to support theSharedArrayBuffer.prototype
built-in methods.
Whenever a
Unlike an ArrayBuffer
, a SharedArrayBuffer
cannot become detached, and its internal [[ArrayBufferData]] slot is never
25.2.3.1 SharedArrayBuffer ( length [ , options ] )
This function performs the following steps when called:
- If NewTarget is
undefined , throw aTypeError exception. - Let byteLength be ?
ToIndex (length). - Let requestedMaxByteLength be ?
GetArrayBufferMaxByteLengthOption (options). - Return ?
AllocateSharedArrayBuffer (NewTarget, byteLength, requestedMaxByteLength).
25.2.4 Properties of the SharedArrayBuffer Constructor
The SharedArrayBuffer
- has a [[Prototype]] internal slot whose value is
%Function.prototype% . - has the following properties:
25.2.4.1 SharedArrayBuffer.prototype
The initial value of SharedArrayBuffer.prototype
is the
This property has the attributes { [[Writable]]:
25.2.4.2 get SharedArrayBuffer [ @@species ]
SharedArrayBuffer[@@species]
is an
- Return the
this value.
The value of the
25.2.5 Properties of the SharedArrayBuffer Prototype Object
The SharedArrayBuffer prototype object:
- is %SharedArrayBuffer.prototype%.
- has a [[Prototype]] internal slot whose value is
%Object.prototype% . - is an
ordinary object . - does not have an [[ArrayBufferData]] or [[ArrayBufferByteLength]] internal slot.
25.2.5.1 get SharedArrayBuffer.prototype.byteLength
SharedArrayBuffer.prototype.byteLength
is an
- Let O be the
this value. - Perform ?
RequireInternalSlot (O, [[ArrayBufferData]]). - If
IsSharedArrayBuffer (O) isfalse , throw aTypeError exception. - Let length be
ArrayBufferByteLength (O,seq-cst ). - Return
𝔽 (length).
25.2.5.2 SharedArrayBuffer.prototype.constructor
The initial value of SharedArrayBuffer.prototype.constructor
is
25.2.5.3 SharedArrayBuffer.prototype.grow ( newLength )
This method performs the following steps when called:
- Let O be the
this value. - Perform ?
RequireInternalSlot (O, [[ArrayBufferMaxByteLength]]). - If
IsSharedArrayBuffer (O) isfalse , throw aTypeError exception. - Let newByteLength be ?
ToIndex (newLength). - Let hostHandled be ?
HostGrowSharedArrayBuffer (O, newByteLength). - If hostHandled is
handled , returnundefined . - Let isLittleEndian be the value of the [[LittleEndian]] field of the
surrounding agent 'sAgent Record . - Let byteLengthBlock be O.[[ArrayBufferByteLengthData]].
- Let currentByteLengthRawBytes be
GetRawBytesFromSharedBlock (byteLengthBlock, 0,biguint64 ,true ,seq-cst ). - Let newByteLengthRawBytes be
NumericToRawBytes (biguint64 ,ℤ (newByteLength), isLittleEndian). - Repeat,
- NOTE: This is a compare-and-exchange loop to ensure that parallel, racing grows of the same buffer are totally ordered, are not lost, and do not silently do nothing. The loop exits if it was able to attempt to grow uncontended.
- Let currentByteLength be
ℝ (RawBytesToNumeric (biguint64 , currentByteLengthRawBytes, isLittleEndian)). - If newByteLength = currentByteLength, return
undefined . - If newByteLength < currentByteLength or newByteLength > O.[[ArrayBufferMaxByteLength]], throw a
RangeError exception. - Let byteLengthDelta be newByteLength - currentByteLength.
- If it is impossible to create a new
Shared Data Block value consisting of byteLengthDelta bytes, throw aRangeError exception. - NOTE: No new
Shared Data Block is constructed and used here. The observable behaviour of growable SharedArrayBuffers is specified by allocating amax -sizedShared Data Block at construction time, and this step captures the requirement that implementations that run out of memory must throw aRangeError . - Let readByteLengthRawBytes be
AtomicCompareExchangeInSharedBlock (byteLengthBlock, 0, 8, currentByteLengthRawBytes, newByteLengthRawBytes). - If
ByteListEqual (readByteLengthRawBytes, currentByteLengthRawBytes) istrue , returnundefined . - Set currentByteLengthRawBytes to readByteLengthRawBytes.
Spurious failures of the compare-exchange to update the length are prohibited. If the bounds checking for the new length passes and the implementation is not out of memory, a
Parallel calls to SharedArrayBuffer.prototype.grow are totally ordered. For example, consider two racing calls: sab.grow(10)
and sab.grow(20)
. One of the two calls is guaranteed to win the race. The call to sab.grow(10)
will never shrink sab
even if sab.grow(20)
happened first; in that case it will instead throw a RangeError.
25.2.5.4 get SharedArrayBuffer.prototype.growable
SharedArrayBuffer.prototype.growable
is an
- Let O be the
this value. - Perform ?
RequireInternalSlot (O, [[ArrayBufferData]]). - If
IsSharedArrayBuffer (O) isfalse , throw aTypeError exception. - If
IsFixedLengthArrayBuffer (O) isfalse , returntrue ; otherwise returnfalse .
25.2.5.5 get SharedArrayBuffer.prototype.maxByteLength
SharedArrayBuffer.prototype.maxByteLength
is an
- Let O be the
this value. - Perform ?
RequireInternalSlot (O, [[ArrayBufferData]]). - If
IsSharedArrayBuffer (O) isfalse , throw aTypeError exception. - If
IsFixedLengthArrayBuffer (O) istrue , then- Let length be O.[[ArrayBufferByteLength]].
- Else,
- Let length be O.[[ArrayBufferMaxByteLength]].
- Return
𝔽 (length).
25.2.5.6 SharedArrayBuffer.prototype.slice ( start, end )
This method performs the following steps when called:
- Let O be the
this value. - Perform ?
RequireInternalSlot (O, [[ArrayBufferData]]). - If
IsSharedArrayBuffer (O) isfalse , throw aTypeError exception. - Let len be
ArrayBufferByteLength (O,seq-cst ). - Let relativeStart be ?
ToIntegerOrInfinity (start). - If relativeStart = -∞, let first be 0.
- Else if relativeStart < 0, let first be
max (len + relativeStart, 0). - Else, let first be
min (relativeStart, len). - If end is
undefined , let relativeEnd be len; else let relativeEnd be ?ToIntegerOrInfinity (end). - If relativeEnd = -∞, let final be 0.
- Else if relativeEnd < 0, let final be
max (len + relativeEnd, 0). - Else, let final be
min (relativeEnd, len). - Let newLen be
max (final - first, 0). - Let ctor be ?
SpeciesConstructor (O,%SharedArrayBuffer% ). - Let new be ?
Construct (ctor, «𝔽 (newLen) »). - Perform ?
RequireInternalSlot (new, [[ArrayBufferData]]). - If
IsSharedArrayBuffer (new) isfalse , throw aTypeError exception. - If new.[[ArrayBufferData]] is O.[[ArrayBufferData]], throw a
TypeError exception. - If
ArrayBufferByteLength (new,seq-cst ) < newLen, throw aTypeError exception. - Let fromBuf be O.[[ArrayBufferData]].
- Let toBuf be new.[[ArrayBufferData]].
- Perform
CopyDataBlockBytes (toBuf, 0, fromBuf, first, newLen). - Return new.
25.2.5.7 SharedArrayBuffer.prototype [ @@toStringTag ]
The initial value of the
This property has the attributes { [[Writable]]:
25.2.6 Properties of SharedArrayBuffer Instances
SharedArrayBuffer instances inherit properties from the
SharedArrayBuffer instances, unlike ArrayBuffer instances, are never detached.
25.2.7 Growable SharedArrayBuffer Guidelines
The following are guidelines for ECMAScript programmers working with
We recommend that programs be tested in their deployment environments where possible. The amount of available physical memory differ greatly between hardware devices. Similarly, virtual memory subsystems also differ greatly between hardware devices as well as operating systems. An application that runs without out-of-memory errors on a 64-bit desktop web browser could run out of memory on a 32-bit mobile web browser.
When choosing a value for the
Please note that successfully constructing a
Not all loads of a u8[idx]
, are not synchronizing. In general, in the absence of explicit synchronization, one property access being in-bound does not imply a subsequent property access in the same length
and byteLength
getters on SharedArrayBuffer,
The following are guidelines for ECMAScript implementers implementing
We recommend
Because grow operations can happen in parallel with memory accesses on a
Grown memory must appear zeroed from the moment of its creation, including to any racy accesses in parallel. This can be accomplished via zero-filled-on-demand virtual memory pages, or careful synchronization if manually zeroing memory.
In practice it is difficult to implement