| Index: src/typedarray.js
|
| diff --git a/src/typedarray.js b/src/typedarray.js
|
| index d5357b4f2cbdbd3c656041754ac6ea0b863def16..f9e732fa7f8f35bfd13598746c8a02f9af98b2ef 100644
|
| --- a/src/typedarray.js
|
| +++ b/src/typedarray.js
|
| @@ -144,30 +144,103 @@ function CreateSubArray(elementSize, constructor) {
|
| }
|
| }
|
|
|
| +function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
|
| + if (offset > 0) {
|
| + for (var i = 0; i < sourceLength; i++) {
|
| + target[offset + i] = source[i];
|
| + }
|
| + }
|
| + else {
|
| + for (var i = 0; i < sourceLength; i++) {
|
| + target[i] = source[i];
|
| + }
|
| + }
|
| +}
|
| +
|
| +function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
|
| + var sourceElementSize = source.BYTES_PER_ELEMENT;
|
| + var targetElementSize = target.BYTES_PER_ELEMENT;
|
| + var sourceLength = source.length;
|
| +
|
| + // Copy left part.
|
| + function CopyLeftPart() {
|
| + // First un-mutated byte after the next write
|
| + var targetPtr = target.byteOffset + (offset + 1) * targetElementSize;
|
| + // Next read at sourcePtr. We do not care for memory changing before
|
| + // sourcePtr - we have already copied it.
|
| + var sourcePtr = source.byteOffset;
|
| + for (var leftIndex = 0;
|
| + leftIndex < sourceLength && targetPtr <= sourcePtr;
|
| + leftIndex++) {
|
| + target[offset + leftIndex] = source[leftIndex];
|
| + targetPtr += targetElementSize;
|
| + sourcePtr += sourceElementSize;
|
| + }
|
| + return leftIndex;
|
| + }
|
| + var leftIndex = CopyLeftPart();
|
| +
|
| + // Copy rigth part;
|
| + function CopyRightPart() {
|
| + // First unmutated byte before the next write
|
| + var targetPtr =
|
| + target.byteOffset + (offset + sourceLength - 1) * targetElementSize;
|
| + // Next read before sourcePtr. We do not care for memory changing after
|
| + // sourcePtr - we have already copied it.
|
| + var sourcePtr =
|
| + source.byteOffset + sourceLength * sourceElementSize;
|
| + for(var rightIndex = sourceLength - 1;
|
| + rightIndex >= leftIndex && targetPtr >= sourcePtr;
|
| + rightIndex--) {
|
| + target[offset + rightIndex] = source[rightIndex];
|
| + targetPtr -= targetElementSize;
|
| + sourcePtr -= sourceElementSize;
|
| + }
|
| + return rightIndex;
|
| + }
|
| + var rightIndex = CopyRightPart();
|
| +
|
| + var temp = new $Array(rightIndex + 1 - leftIndex);
|
| + for (var i = leftIndex; i <= rightIndex; i++) {
|
| + temp[i - leftIndex] = source[i];
|
| + }
|
| + for (i = leftIndex; i <= rightIndex; i++) {
|
| + target[offset + i] = temp[i - leftIndex];
|
| + }
|
| +}
|
| +
|
| function TypedArraySet(obj, offset) {
|
| var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
|
| if (intOffset < 0) {
|
| throw MakeTypeError("typed_array_set_negative_offset");
|
| }
|
| - if (%TypedArraySetFastCases(this, obj, intOffset))
|
| - return;
|
| -
|
| - var l = obj.length;
|
| - if (IS_UNDEFINED(l)) {
|
| - if (IS_NUMBER(obj)) {
|
| - // For number as a first argument, throw TypeError
|
| - // instead of silently ignoring the call, so that
|
| - // the user knows (s)he did something wrong.
|
| - // (Consistent with Firefox and Blink/WebKit)
|
| - throw MakeTypeError("invalid_argument");
|
| - }
|
| - return;
|
| - }
|
| - if (intOffset + l > this.length) {
|
| - throw MakeRangeError("typed_array_set_source_too_large");
|
| - }
|
| - for (var i = 0; i < l; i++) {
|
| - this[intOffset + i] = obj[i];
|
| + switch (%TypedArraySetFastCases(this, obj, intOffset)) {
|
| + // These numbers should be synchronized with runtime.cc.
|
| + case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE
|
| + return;
|
| + case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING
|
| + TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
|
| + return;
|
| + case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
|
| + TypedArraySetFromArrayLike(this, obj, obj.length, intOffset);
|
| + return;
|
| + case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
|
| + var l = obj.length;
|
| + if (IS_UNDEFINED(l)) {
|
| + if (IS_NUMBER(obj)) {
|
| + // For number as a first argument, throw TypeError
|
| + // instead of silently ignoring the call, so that
|
| + // the user knows (s)he did something wrong.
|
| + // (Consistent with Firefox and Blink/WebKit)
|
| + throw MakeTypeError("invalid_argument");
|
| + }
|
| + return;
|
| + }
|
| + if (intOffset + l > this.length) {
|
| + throw MakeRangeError("typed_array_set_source_too_large");
|
| + }
|
| + TypedArraySetFromArrayLike(this, obj, l, intOffset);
|
| + return;
|
| }
|
| }
|
|
|
|
|