Skip to content

Commit

Permalink
Normative: In the TypedArray(typedArray) constructor, copy only the n…
Browse files Browse the repository at this point in the history
…eeded portion (#458)

The TypedArray constructor includes a "fast path" for a TypedArray input (as
opposed to treating it as an iterable), which has a fast path for the case of
the same-type input and output. This path calls CloneArrayBuffer.
CloneArrayBuffer takes an argument for the start offset, but it did not take
an argument for the end, so it copied the underlying ArrayBuffer until the
end. The extra wasted copy remains observable, e.g. in cases like

new Uint8Array(new Uint8Array(10000).subarray(0, 1)).buffer.byteLength // => 1 or 10000 ?

This patch adds an additional argument to CloneArrayBuffer for the length
in bytes that should be cloned, so that only the viewed portion of the
ArrayBuffer is copied.
This does not make an observable change for the other caller
(%TypedArray%.prototype.set), where it would have already been valid to apply
this optimization.

Closes #447
  • Loading branch information
littledan authored and bterlson committed Apr 18, 2016
1 parent e025c0c commit e1cecfa
Showing 1 changed file with 7 additions and 9 deletions.
16 changes: 7 additions & 9 deletions spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -31412,8 +31412,8 @@ <h1>%TypedArray%.prototype.set(_typedArray_ [ , _offset_ ] )</h1>
1. Let _srcByteOffset_ be the value of _typedArray_'s [[ByteOffset]] internal slot.
1. If _srcLength_ + _targetOffset_ &gt; _targetLength_, throw a *RangeError* exception.
1. If SameValue(_srcBuffer_, _targetBuffer_) is *true*, then
1. Let _srcBuffer_ be ? CloneArrayBuffer(_targetBuffer_, _srcByteOffset_, %ArrayBuffer%).
1. NOTE: %ArrayBuffer% is used to clone _targetBuffer_ because is it known to not have any observable side-effects.
1. Let _srcBuffer_ be ? CloneArrayBuffer(_srcBuffer_, _srcByteOffset_, _srcLength_, %ArrayBuffer%).
1. NOTE: %ArrayBuffer% is used to clone _srcBuffer_ because is it known to not have any observable side-effects.
1. Let _srcByteIndex_ be 0.
1. Else, let _srcByteIndex_ be _srcByteOffset_.
1. Let _targetByteIndex_ be _targetOffset_ &times; _targetElementSize_ + _targetByteOffset_.
Expand Down Expand Up @@ -31698,7 +31698,8 @@ <h1>_TypedArray_ ( _typedArray_ )</h1>
1. Let _elementSize_ be the Element Size value in <emu-xref href="#table-49"></emu-xref> for _constructorName_.
1. Let _byteLength_ be _elementSize_ &times; _elementLength_.
1. If SameValue(_elementType_, _srcType_) is *true*, then
1. Let _data_ be ? CloneArrayBuffer(_srcData_, _srcByteOffset_).
1. Let _srcLength_ be the value of _typedArray_'s [[ByteLength]] internal slot.
1. Let _data_ be ? CloneArrayBuffer(_srcData_, _srcByteOffset_, _srcLength_).
1. Else,
1. Let _bufferConstructor_ be ? SpeciesConstructor(_srcData_, %ArrayBuffer%).
1. Let _data_ be ? AllocateArrayBuffer(_bufferConstructor_, _byteLength_).
Expand Down Expand Up @@ -32944,19 +32945,16 @@ <h1>DetachArrayBuffer ( _arrayBuffer_ )</h1>

<!-- es6num="24.1.1.4" -->
<emu-clause id="sec-clonearraybuffer" aoid="CloneArrayBuffer">
<h1>CloneArrayBuffer ( _srcBuffer_, _srcByteOffset_ [ , _cloneConstructor_ ] )</h1>
<p>The abstract operation CloneArrayBuffer takes three parameters, an ArrayBuffer _srcBuffer_, an integer _srcByteOffset_ and optionally a constructor function _cloneConstructor_. It creates a new ArrayBuffer whose data is a copy of _srcBuffer_'s data starting at _srcByteOffset_. This operation performs the following steps:</p>
<h1>CloneArrayBuffer ( _srcBuffer_, _srcByteOffset_, _srcLength_, [ , _cloneConstructor_ ] )</h1>
<p>The abstract operation CloneArrayBuffer takes four parameters, an ArrayBuffer _srcBuffer_, a source buffer _srcBuffer_, an integer offset _srcByteOffset_ an integer length _srcLength_, and optionally a constructor function _cloneConstructor_. It creates a new ArrayBuffer whose data is a copy of _srcBuffer_'s data over the range starting at _srcByteOffset_ and continuing for _srcLength_ bytes. This operation performs the following steps:</p>
<emu-alg>
1. Assert: Type(_srcBuffer_) is Object and it has an [[ArrayBufferData]] internal slot.
1. If _cloneConstructor_ is not present, then
1. Let _cloneConstructor_ be ? SpeciesConstructor(_srcBuffer_, %ArrayBuffer%).
1. If IsDetachedBuffer(_srcBuffer_) is *true*, throw a *TypeError* exception.
1. Else, Assert: IsConstructor(_cloneConstructor_) is *true*.
1. Let _srcLength_ be the value of _srcBuffer_'s [[ArrayBufferByteLength]] internal slot.
1. Assert: _srcByteOffset_ &le; _srcLength_.
1. Let _cloneLength_ be _srcLength_ - _srcByteOffset_.
1. Let _srcBlock_ be the value of _srcBuffer_'s [[ArrayBufferData]] internal slot.
1. Let _targetBuffer_ be ? AllocateArrayBuffer(_cloneConstructor_, _cloneLength_).
1. Let _targetBuffer_ be ? AllocateArrayBuffer(_cloneConstructor_, _srcLength_).
1. If IsDetachedBuffer(_srcBuffer_) is *true*, throw a *TypeError* exception.
1. Let _targetBlock_ be the value of _targetBuffer_'s [[ArrayBufferData]] internal slot.
1. Perform CopyDataBlockBytes(_targetBlock_, 0, _srcBlock_, _srcByteOffset_, _cloneLength_).
Expand Down

0 comments on commit e1cecfa

Please sign in to comment.