Diff
Modified: trunk/LayoutTests/ChangeLog (154517 => 154518)
--- trunk/LayoutTests/ChangeLog 2013-08-23 20:35:09 UTC (rev 154517)
+++ trunk/LayoutTests/ChangeLog 2013-08-23 20:40:34 UTC (rev 154518)
@@ -1,3 +1,43 @@
+2013-08-23 Filip Pizlo <[email protected]>
+
+ Incorrect TypedArray#set behavior
+ https://bugs.webkit.org/show_bug.cgi?id=83818
+
+ Reviewed by Oliver Hunt and Mark Hahnenberg.
+
+ Made it possible for shouldBe() to compare typed arrays to each other and to any array-like
+ object.
+
+ Added a bunch of tests for different kinds of overlapping typedArray.set()'s.
+
+ For sanity, also added the reduced test case from the bug. Interestingly, though, that test
+ case already passed on trunk - probably by luck (we had incidentally changed the default
+ copy direction from one that happened to not work to one that happened to be fine, but only
+ for this test).
+
+ * fast/js/jsc-test-list:
+ * fast/js/resources/js-test-pre.js:
+ (isTypedArray):
+ (isResultCorrect):
+ (stringify):
+ (shouldBe):
+ * fast/js/script-tests/typed-array-copy.js: Added.
+ * fast/js/script-tests/typedarray-set-destination-smaller-than-source.js: Added.
+ * fast/js/script-tests/typedarray-set-overlapping-elements-of-same-size.js: Added.
+ * fast/js/script-tests/typedarray-set-same-type-memmove.js: Added.
+ (arraysEqual):
+ * fast/js/script-tests/typedarray-set-source-smaller-than-destination.js: Added.
+ * fast/js/typed-array-copy-expected.txt: Added.
+ * fast/js/typed-array-copy.html: Added.
+ * fast/js/typedarray-set-destination-smaller-than-source-expected.txt: Added.
+ * fast/js/typedarray-set-destination-smaller-than-source.html: Added.
+ * fast/js/typedarray-set-overlapping-elements-of-same-size-expected.txt: Added.
+ * fast/js/typedarray-set-overlapping-elements-of-same-size.html: Added.
+ * fast/js/typedarray-set-same-type-memmove-expected.txt: Added.
+ * fast/js/typedarray-set-same-type-memmove.html: Added.
+ * fast/js/typedarray-set-source-smaller-than-destination-expected.txt: Added.
+ * fast/js/typedarray-set-source-smaller-than-destination.html: Added.
+
2013-08-23 Andre Moreira Magalhaes <[email protected]>
LayoutTests/http/tests/media/video-throttled-load.cgi issue on range support
Modified: trunk/LayoutTests/fast/js/jsc-test-list (154517 => 154518)
--- trunk/LayoutTests/fast/js/jsc-test-list 2013-08-23 20:35:09 UTC (rev 154517)
+++ trunk/LayoutTests/fast/js/jsc-test-list 2013-08-23 20:40:34 UTC (rev 154518)
@@ -437,6 +437,11 @@
fast/js/toString-recursion
fast/js/try-catch-try-try-catch-try-finally-return-catch-finally
fast/js/try-try-return-finally-finally
+fast/js/typed-array-copy
+fast/js/typedarray-set-destination-smaller-than-source
+fast/js/typedarray-set-overlapping-elements-of-same-size
+fast/js/typedarray-set-same-type-memmove
+fast/js/typedarray-set-source-smaller-than-destination
fast/js/typeof-codegen-crash
fast/js/typeof-constant-string
fast/js/unexpected-constant-crash
Modified: trunk/LayoutTests/fast/js/resources/js-test-pre.js (154517 => 154518)
--- trunk/LayoutTests/fast/js/resources/js-test-pre.js 2013-08-23 20:35:09 UTC (rev 154517)
+++ trunk/LayoutTests/fast/js/resources/js-test-pre.js 2013-08-23 20:40:34 UTC (rev 154518)
@@ -133,6 +133,19 @@
return n === 0 && 1/n < 0;
}
+function isTypedArray(array)
+{
+ return array instanceof Int8Array
+ || array instanceof Int16Array
+ || array instanceof Int32Array
+ || array instanceof Uint8Array
+ || array instanceof Uint8ClampedArray
+ || array instanceof Uint16Array
+ || array instanceof Uint32Array
+ || array instanceof Float32Array
+ || array instanceof Float64Array;
+}
+
function isResultCorrect(_actual, _expected)
{
if (_expected === 0)
@@ -141,7 +154,10 @@
return true;
if (typeof(_expected) == "number" && isNaN(_expected))
return typeof(_actual) == "number" && isNaN(_actual);
- if (_expected && (Object.prototype.toString.call(_expected) == Object.prototype.toString.call([])))
+ if (_expected
+ && (Object.prototype.toString.call(_expected) ==
+ Object.prototype.toString.call([])
+ || isTypedArray(_expected)))
return areArraysEqual(_actual, _expected);
return false;
}
@@ -150,7 +166,10 @@
{
if (v === 0 && 1/v < 0)
return "-0";
- else return "" + v;
+ else if (isTypedArray(v))
+ return v.__proto__.constructor.name + ":[" + Array.prototype.join.call(v, ",") + "]";
+ else
+ return "" + v;
}
function evalAndLog(_a, _quiet)
@@ -185,15 +204,15 @@
var _bv = eval(_b);
if (exception)
- testFailed(_a + " should be " + _bv + ". Threw exception " + exception);
+ testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + exception);
else if (isResultCorrect(_av, _bv)) {
if (!quiet) {
testPassed(_a + " is " + _b);
}
} else if (typeof(_av) == typeof(_bv))
- testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
+ testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
else
- testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
+ testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
}
// Execute condition every 5 milliseconds until it succeed or failureTime is reached.
Added: trunk/LayoutTests/fast/js/script-tests/typed-array-copy.js (0 => 154518)
--- trunk/LayoutTests/fast/js/script-tests/typed-array-copy.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/typed-array-copy.js 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,16 @@
+description(
+"Reduced test case for https://bugs.webkit.org/show_bug.cgi?id=83818"
+);
+
+a = new Uint16Array(8);
+
+b = new Uint8Array(a.buffer, 0, 2);
+b[0] = 0x05;
+b[1] = 0x05;
+
+shouldBe("a[0]", "0x0505");
+
+a.set(b);
+
+shouldBe("a[0]", "0x0005");
+shouldBe("a[1]", "0x0005");
Added: trunk/LayoutTests/fast/js/script-tests/typedarray-set-destination-smaller-than-source.js (0 => 154518)
--- trunk/LayoutTests/fast/js/script-tests/typedarray-set-destination-smaller-than-source.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/typedarray-set-destination-smaller-than-source.js 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,58 @@
+description(
+"Tests the code path in typedArray.set that may have to do a copy via an intermediate buffer because the source and destination overlap and have different size elements (source is larger than destination)."
+);
+
+function foo_reference(n) {
+ var array = new Int8Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ var array2 = new Int8Array(array);
+ array2.set(new Int32Array(array.buffer));
+ return array2;
+}
+
+function foo(n) {
+ var array = new Int8Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(new Int32Array(array.buffer));
+ return array;
+}
+
+function bar_reference(n) {
+ var array = new Int8Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ var array2 = new Int8Array(array);
+ array2.set(new Int32Array(array.buffer), n - n / 4);
+ return array2;
+}
+
+function bar(n) {
+ var array = new Int8Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(new Int32Array(array.buffer), n - n / 4);
+ return array;
+}
+
+function baz_reference(n) {
+ var array = new Int8Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ var array2 = new Int8Array(array);
+ array2.set(new Int32Array(array.buffer), n / 2 - (n / 4) / 2);
+ return array2;
+}
+
+function baz(n) {
+ var array = new Int8Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(new Int32Array(array.buffer), n / 2 - (n / 4) / 2);
+ return array;
+}
+
+shouldBe("foo(64)", "foo_reference(64)");
+shouldBe("bar(64)", "bar_reference(64)");
+shouldBe("baz(64)", "baz_reference(64)");
Added: trunk/LayoutTests/fast/js/script-tests/typedarray-set-overlapping-elements-of-same-size.js (0 => 154518)
--- trunk/LayoutTests/fast/js/script-tests/typedarray-set-overlapping-elements-of-same-size.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/typedarray-set-overlapping-elements-of-same-size.js 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,23 @@
+description(
+"Tests the code path of typedArray.set that tries to do a memmove-with-conversion for overlapping arrays."
+);
+
+function foo(n) {
+ var array = new Int32Array(n + 1);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(new Uint32Array(array.buffer, 0, n), 1);
+ return array;
+}
+
+function bar(n) {
+ var array = new Int32Array(n + 1);
+ for (var i = 0; i < n; ++i)
+ array[i + 1] = 42 + i;
+ array.set(new Uint32Array(array.buffer, 4), 0);
+ return array;
+}
+
+shouldBe("foo(10)", "[42,42,42,42,42,42,42,42,42,42,42]");
+shouldBe("bar(10)", "[42,43,44,45,46,47,48,49,50,51,51]");
+
Added: trunk/LayoutTests/fast/js/script-tests/typedarray-set-same-type-memmove.js (0 => 154518)
--- trunk/LayoutTests/fast/js/script-tests/typedarray-set-same-type-memmove.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/typedarray-set-same-type-memmove.js 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,27 @@
+description(
+"Tests the code path of typedArray.set that bottoms out in memmove."
+);
+
+function foo(n) {
+ var array = new Int32Array(n + 1);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(array.subarray(0, n), 1);
+ return array;
+}
+
+function bar(n) {
+ var array = new Int32Array(n + 1);
+ for (var i = 0; i < n; ++i)
+ array[i + 1] = 42 + i;
+ array.set(array.subarray(1, n + 1), 0);
+ return array;
+}
+
+function arraysEqual(a, b) {
+ if (a.length != b.length)
+ return false;
+}
+
+shouldBe("foo(10)", "[42,42,43,44,45,46,47,48,49,50,51]");
+shouldBe("bar(10)", "[42,43,44,45,46,47,48,49,50,51,51]");
Added: trunk/LayoutTests/fast/js/script-tests/typedarray-set-source-smaller-than-destination.js (0 => 154518)
--- trunk/LayoutTests/fast/js/script-tests/typedarray-set-source-smaller-than-destination.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/typedarray-set-source-smaller-than-destination.js 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,95 @@
+description(
+"Tests the code path in typedArray.set that may have to do a copy via an intermediate buffer because the source and destination overlap and have different size elements (source is smaller than destination)."
+);
+
+function foo_reference(n) {
+ var array = new Int32Array(n + 1);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ var array2 = new Int32Array(array);
+ array2.set(new Uint8Array(array.buffer, 0, n), 1);
+ return array2;
+}
+
+function foo(n) {
+ var array = new Int32Array(n + 1);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(new Uint8Array(array.buffer, 0, n), 1);
+ return array;
+}
+
+function bar_reference(n) {
+ var array = new Int32Array(n + 1);
+ for (var i = 0; i < n; ++i)
+ array[i + 1] = 42 + i;
+ var array2 = new Int32Array(array);
+ array2.set(new Uint8Array(array.buffer, (n + 1) * 4 - n), 0);
+ return array2;
+}
+
+function bar(n) {
+ var array = new Int32Array(n + 1);
+ for (var i = 0; i < n; ++i)
+ array[i + 1] = 42 + i;
+ array.set(new Uint8Array(array.buffer, (n + 1) * 4 - n), 0);
+ return array;
+}
+
+function baz_reference(n) {
+ var array = new Int32Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ var array2 = new Int32Array(array);
+ array2.set(new Uint8Array(array.buffer, 0, n));
+ return array2;
+}
+
+function baz(n) {
+ var array = new Int32Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(new Uint8Array(array.buffer, 0, n));
+ return array;
+}
+
+function fuz_reference(n) {
+ var array = new Int32Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ var array2 = new Int32Array(array);
+ array2.set(new Uint8Array(array.buffer, n * 4 - n));
+ return array2;
+}
+
+function fuz(n) {
+ var array = new Int32Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(new Uint8Array(array.buffer, n * 4 - n));
+ return array;
+}
+
+function thingy_reference(n) {
+ var array = new Int32Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ var array2 = new Int32Array(array);
+ array2.set(new Uint8Array(array.buffer, 4, n));
+ return array2;
+}
+
+function thingy(n) {
+ var array = new Int32Array(n);
+ for (var i = 0; i < n; ++i)
+ array[i] = 42 + i;
+ array.set(new Uint8Array(array.buffer, 4, n));
+ return array;
+}
+
+shouldBe("foo(10)", "foo_reference(10)");
+shouldBe("bar(10)", "bar_reference(10)");
+shouldBe("baz(10)", "baz_reference(10)");
+shouldBe("fuz(10)", "fuz_reference(10)");
+shouldBe("thingy(10)", "thingy_reference(10)");
+
Added: trunk/LayoutTests/fast/js/typed-array-copy-expected.txt (0 => 154518)
--- trunk/LayoutTests/fast/js/typed-array-copy-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/typed-array-copy-expected.txt 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,12 @@
+Reduced test case for https://bugs.webkit.org/show_bug.cgi?id=83818
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS a[0] is 0x0505
+PASS a[0] is 0x0005
+PASS a[1] is 0x0005
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/typed-array-copy.html (0 => 154518)
--- trunk/LayoutTests/fast/js/typed-array-copy.html (rev 0)
+++ trunk/LayoutTests/fast/js/typed-array-copy.html 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/typedarray-set-destination-smaller-than-source-expected.txt (0 => 154518)
--- trunk/LayoutTests/fast/js/typedarray-set-destination-smaller-than-source-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/typedarray-set-destination-smaller-than-source-expected.txt 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,12 @@
+Tests the code path in typedArray.set that may have to do a copy via an intermediate buffer because the source and destination overlap and have different size elements (source is larger than destination).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo(64) is foo_reference(64)
+PASS bar(64) is bar_reference(64)
+PASS baz(64) is baz_reference(64)
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/typedarray-set-destination-smaller-than-source.html (0 => 154518)
--- trunk/LayoutTests/fast/js/typedarray-set-destination-smaller-than-source.html (rev 0)
+++ trunk/LayoutTests/fast/js/typedarray-set-destination-smaller-than-source.html 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/typedarray-set-overlapping-elements-of-same-size-expected.txt (0 => 154518)
--- trunk/LayoutTests/fast/js/typedarray-set-overlapping-elements-of-same-size-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/typedarray-set-overlapping-elements-of-same-size-expected.txt 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,11 @@
+Tests the code path of typedArray.set that tries to do a memmove-with-conversion for overlapping arrays.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo(10) is [42,42,42,42,42,42,42,42,42,42,42]
+PASS bar(10) is [42,43,44,45,46,47,48,49,50,51,51]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/typedarray-set-overlapping-elements-of-same-size.html (0 => 154518)
--- trunk/LayoutTests/fast/js/typedarray-set-overlapping-elements-of-same-size.html (rev 0)
+++ trunk/LayoutTests/fast/js/typedarray-set-overlapping-elements-of-same-size.html 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/typedarray-set-same-type-memmove-expected.txt (0 => 154518)
--- trunk/LayoutTests/fast/js/typedarray-set-same-type-memmove-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/typedarray-set-same-type-memmove-expected.txt 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,11 @@
+Tests the code path of typedArray.set that bottoms out in memmove.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo(10) is [42,42,43,44,45,46,47,48,49,50,51]
+PASS bar(10) is [42,43,44,45,46,47,48,49,50,51,51]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/typedarray-set-same-type-memmove.html (0 => 154518)
--- trunk/LayoutTests/fast/js/typedarray-set-same-type-memmove.html (rev 0)
+++ trunk/LayoutTests/fast/js/typedarray-set-same-type-memmove.html 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/typedarray-set-source-smaller-than-destination-expected.txt (0 => 154518)
--- trunk/LayoutTests/fast/js/typedarray-set-source-smaller-than-destination-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/typedarray-set-source-smaller-than-destination-expected.txt 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,14 @@
+Tests the code path in typedArray.set that may have to do a copy via an intermediate buffer because the source and destination overlap and have different size elements (source is smaller than destination).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo(10) is foo_reference(10)
+PASS bar(10) is bar_reference(10)
+PASS baz(10) is baz_reference(10)
+PASS fuz(10) is fuz_reference(10)
+PASS thingy(10) is thingy_reference(10)
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/typedarray-set-source-smaller-than-destination.html (0 => 154518)
--- trunk/LayoutTests/fast/js/typedarray-set-source-smaller-than-destination.html (rev 0)
+++ trunk/LayoutTests/fast/js/typedarray-set-source-smaller-than-destination.html 2013-08-23 20:40:34 UTC (rev 154518)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Modified: trunk/Source/_javascript_Core/ChangeLog (154517 => 154518)
--- trunk/Source/_javascript_Core/ChangeLog 2013-08-23 20:35:09 UTC (rev 154517)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-08-23 20:40:34 UTC (rev 154518)
@@ -1,3 +1,29 @@
+2013-08-23 Filip Pizlo <[email protected]>
+
+ Incorrect TypedArray#set behavior
+ https://bugs.webkit.org/show_bug.cgi?id=83818
+
+ Reviewed by Oliver Hunt and Mark Hahnenberg.
+
+ This was so much fun! typedArray.set() is like a memmove on steroids, and I'm
+ not smart enough to figure out optimal versions for *all* of the cases. But I
+ did come up with optimal implementations for most of the cases, and I wrote
+ spec-literal code (i.e. copy via a transfer buffer) for the cases I'm not smart
+ enough to write optimal code for.
+
+ * runtime/JSArrayBufferView.h:
+ (JSC::JSArrayBufferView::hasArrayBuffer):
+ * runtime/JSArrayBufferViewInlines.h:
+ (JSC::JSArrayBufferView::buffer):
+ (JSC::JSArrayBufferView::existingBufferInButterfly):
+ (JSC::JSArrayBufferView::neuter):
+ (JSC::JSArrayBufferView::byteOffset):
+ * runtime/JSGenericTypedArrayView.h:
+ * runtime/JSGenericTypedArrayViewInlines.h:
+ (JSC::::setWithSpecificType):
+ (JSC::::set):
+ (JSC::::existingBuffer):
+
2013-08-23 Alex Christensen <[email protected]>
Re-separating Win32 and Win64 builds.
Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h (154517 => 154518)
--- trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h 2013-08-23 20:35:09 UTC (rev 154517)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h 2013-08-23 20:40:34 UTC (rev 154518)
@@ -154,6 +154,8 @@
public:
TypedArrayMode mode() const { return m_mode; }
+ bool hasArrayBuffer() const { return JSC::hasArrayBuffer(mode()); }
+
ArrayBuffer* buffer();
PassRefPtr<ArrayBufferView> impl();
void neuter();
@@ -173,6 +175,8 @@
protected:
static const unsigned StructureFlags = OverridesGetPropertyNames | OverridesGetOwnPropertySlot | Base::StructureFlags;
+
+ ArrayBuffer* existingBufferInButterfly();
void* m_vector;
uint32_t m_length;
Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferViewInlines.h (154517 => 154518)
--- trunk/Source/_javascript_Core/runtime/JSArrayBufferViewInlines.h 2013-08-23 20:35:09 UTC (rev 154517)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferViewInlines.h 2013-08-23 20:40:34 UTC (rev 154518)
@@ -36,7 +36,7 @@
{
switch (m_mode) {
case WastefulTypedArray:
- return butterfly()->indexingHeader()->arrayBuffer();
+ return existingBufferInButterfly();
case DataViewMode:
return jsCast<JSDataView*>(this)->buffer();
default:
@@ -44,6 +44,12 @@
}
}
+inline ArrayBuffer* JSArrayBufferView::existingBufferInButterfly()
+{
+ ASSERT(m_mode == WastefulTypedArray);
+ return butterfly()->indexingHeader()->arrayBuffer();
+}
+
inline PassRefPtr<ArrayBufferView> JSArrayBufferView::impl()
{
return methodTable()->getTypedArrayImpl(this);
@@ -51,14 +57,14 @@
inline void JSArrayBufferView::neuter()
{
- ASSERT(hasArrayBuffer(m_mode));
+ ASSERT(hasArrayBuffer());
m_length = 0;
m_vector = 0;
}
inline unsigned JSArrayBufferView::byteOffset()
{
- if (!hasArrayBuffer(m_mode))
+ if (!hasArrayBuffer())
return 0;
ptrdiff_t delta =
Modified: trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayView.h (154517 => 154518)
--- trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayView.h 2013-08-23 20:35:09 UTC (rev 154517)
+++ trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayView.h 2013-08-23 20:40:34 UTC (rev 154518)
@@ -173,10 +173,6 @@
// appropriate exception.
bool validateRange(ExecState*, unsigned offset, unsigned length);
- // Returns true if successful, and false on error; it will throw on error.
- template<typename OtherType>
- bool setWithSpecificType(ExecState*, OtherType*, unsigned offset, unsigned length);
-
// Returns true if successful, and false on error; if it returns false
// then it will have thrown an exception.
bool set(ExecState*, JSObject*, unsigned offset, unsigned length);
@@ -220,6 +216,8 @@
}
}
+ ArrayBuffer* existingBuffer();
+
static const TypedArrayType TypedArrayStorageType = Adaptor::typeValue;
protected:
@@ -246,6 +244,11 @@
// necessary. Note that this never allocates in the GC heap.
static ArrayBuffer* slowDownAndWasteMemory(JSArrayBufferView*);
static PassRefPtr<ArrayBufferView> getTypedArrayImpl(JSArrayBufferView*);
+
+private:
+ // Returns true if successful, and false on error; it will throw on error.
+ template<typename OtherType>
+ bool setWithSpecificType(ExecState*, OtherType*, unsigned offset, unsigned length);
};
template<typename Adaptor>
Modified: trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h (154517 => 154518)
--- trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h 2013-08-23 20:35:09 UTC (rev 154517)
+++ trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h 2013-08-23 20:40:34 UTC (rev 154518)
@@ -151,8 +151,55 @@
return false;
}
+ // This method doesn't support copying between the same array. Note that
+ // set() will only call this if the types differ, which implicitly guarantees
+ // that we can't be the same array. This is relevant because the way we detect
+ // non-overlapping is by checking if either (a) either array doesn't have a
+ // backing buffer or (b) the backing buffers are different, but that doesn't
+ // catch the case where it's the *same* array - fortunately though, this code
+ // path never needs to worry about that case.
+ ASSERT(static_cast<JSCell*>(this) != static_cast<JSCell*>(other));
+
+ // 1) If the two arrays are non-overlapping, we can copy in any order we like
+ // and we don't need an intermediate buffer. Arrays are definitely
+ // non-overlapping if either one of them has no backing buffer (that means
+ // that it *owns* its philosophical backing buffer) or if they have
+ // different backing buffers.
+ // 2) If the two arrays overlap but have the same element size, we can do a
+ // memmove-like copy where we flip-flop direction based on which vector
+ // starts before the other:
+ // A) If the destination vector is before the source vector, then a forward
+ // copy is in order.
+ // B) If the destination vector is after the source vector, then a backward
+ // copy is in order.
+ // 3) If we have different element sizes and there is a chance of overlap then
+ // we need an intermediate vector.
+
+ // NB. Comparisons involving elementSize will be constant-folded by template
+ // specialization.
+
+ // Handle cases (1) and (2B).
+ if (!hasArrayBuffer() || !other->hasArrayBuffer()
+ || existingBuffer() != other->existingBuffer()
+ || (elementSize == OtherType::elementSize && vector() > other->vector())) {
+ for (unsigned i = length; i--;)
+ setIndexQuickly(offset + i, other->getIndexQuickly(i));
+ return true;
+ }
+
+ // Now we either have (2A) or (3) - so first we try to cover (2A).
+ if (elementSize == OtherType::elementSize) {
+ for (unsigned i = 0; i < length; ++i)
+ setIndexQuickly(offset + i, other->getIndexQuickly(i));
+ return true;
+ }
+
+ // Fail: we need an intermediate transfer buffer (i.e. case (3)).
+ Vector<typename Adaptor::Type, 32> transferBuffer(length);
for (unsigned i = length; i--;)
- setIndexQuickly(offset + i, other->getIndexQuickly(i));
+ transferBuffer[i] = Adaptor::toNative(other->getIndexQuickly(i));
+ for (unsigned i = length; i--;)
+ setIndexQuicklyToNativeValue(offset + i, transferBuffer[i]);
return true;
}
@@ -170,7 +217,7 @@
if (!validateRange(exec, offset, length))
return false;
- memcpy(typedVector() + offset, other->typedVector(), other->byteLength());
+ memmove(typedVector() + offset, other->typedVector(), other->byteLength());
return true;
}
@@ -210,6 +257,12 @@
}
template<typename Adaptor>
+ArrayBuffer* JSGenericTypedArrayView<Adaptor>::existingBuffer()
+{
+ return existingBufferInButterfly();
+}
+
+template<typename Adaptor>
bool JSGenericTypedArrayView<Adaptor>::getOwnPropertySlot(
JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{