Title: [286639] trunk
Revision
286639
Author
[email protected]
Date
2021-12-07 19:59:13 -0800 (Tue, 07 Dec 2021)

Log Message

TypedArray prototype set should go down the fast path when using non clamped integer types of the same byte size
https://bugs.webkit.org/show_bug.cgi?id=233905

Reviewed by Keith Miller.

JSTests:

* microbenchmarks/typed-array-prototype-set.js: Added.
* microbenchmarks/typed-array-prototype-set-order.js: Added.
* stress/typed-array-prototype-set.js: Added.

Source/_javascript_Core:

We can use memmove in this scenario because the bitpattern of the
data between the signed and unsigned values will be the same.

This patch also fixes a bug where we were looking at the wrong
pointer when determining to do a forward or backwards loop in
our memmove. We were looking at the vector instead of vector+offset.

* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView<Adaptor>::set):

LayoutTests:

* js/script-tests/typedarray-set-overlapping-elements-of-same-size.js:
* js/typedarray-set-overlapping-elements-of-same-size-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (286638 => 286639)


--- trunk/JSTests/ChangeLog	2021-12-08 02:49:51 UTC (rev 286638)
+++ trunk/JSTests/ChangeLog	2021-12-08 03:59:13 UTC (rev 286639)
@@ -1,3 +1,14 @@
+2021-12-07  Saam Barati  <[email protected]>
+
+        TypedArray prototype set should go down the fast path when using non clamped integer types of the same byte size
+        https://bugs.webkit.org/show_bug.cgi?id=233905
+
+        Reviewed by Keith Miller.
+
+        * microbenchmarks/typed-array-prototype-set.js: Added.
+        * microbenchmarks/typed-array-prototype-set-order.js: Added.
+        * stress/typed-array-prototype-set.js: Added.
+
 2021-12-02  Yusuke Suzuki  <[email protected]>
 
         [JSC] shell's $.globalObjectFor is not safe for non object cells

Added: trunk/JSTests/microbenchmarks/typed-array-prototype-set.js (0 => 286639)


--- trunk/JSTests/microbenchmarks/typed-array-prototype-set.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/typed-array-prototype-set.js	2021-12-08 03:59:13 UTC (rev 286639)
@@ -0,0 +1,46 @@
+function test() {
+    let x = new Int8Array(10000);
+    let y = new Uint8Array(10000);
+    for (let i = 0; i < x.length; ++i)
+        x[i] = i;
+    for (let i = 0; i < 500; ++i)
+        y.set(x);
+    for (let i = 0; i < 500; ++i)
+        x.set(y);
+}
+
+function test2() {
+    let x = new Int16Array(10000);
+    let y = new Uint16Array(10000);
+    for (let i = 0; i < x.length; ++i)
+        x[i] = i;
+    for (let i = 0; i < 500; ++i)
+        y.set(x);
+    for (let i = 0; i < 500; ++i)
+        x.set(y);
+}
+
+function test3() {
+    let x = new Int32Array(10000);
+    let y = new Uint32Array(10000);
+    for (let i = 0; i < x.length; ++i)
+        x[i] = i;
+    for (let i = 0; i < 500; ++i)
+        y.set(x);
+    for (let i = 0; i < 500; ++i)
+        x.set(y);
+}
+
+function test4() {
+    let x = new Uint8ClampedArray(10000);
+    let y = new Int8Array(10000);
+    for (let i = 0; i < x.length; ++i)
+        x[i] = i;
+    for (let i = 0; i < 500; ++i)
+        y.set(x);
+}
+
+test();
+test2();
+test3();
+test4();

Added: trunk/JSTests/stress/typed-array-prototype-set-order.js (0 => 286639)


--- trunk/JSTests/stress/typed-array-prototype-set-order.js	                        (rev 0)
+++ trunk/JSTests/stress/typed-array-prototype-set-order.js	2021-12-08 03:59:13 UTC (rev 286639)
@@ -0,0 +1,13 @@
+function assert(b) {
+    if (!b)
+        throw new Error;
+}
+
+function foo(n) {
+    var array = new Uint8ClampedArray(n + 1);
+    for (var i = 0; i < n; ++i)
+        array[i] = 42 + i;
+    array.set(new Int8Array(array.buffer, 0, n), 1);
+    return array;
+}
+assert(foo(10).toString() === "42,42,43,44,45,46,47,48,49,50,51");

Added: trunk/JSTests/stress/typed-array-prototype-set.js (0 => 286639)


--- trunk/JSTests/stress/typed-array-prototype-set.js	                        (rev 0)
+++ trunk/JSTests/stress/typed-array-prototype-set.js	2021-12-08 03:59:13 UTC (rev 286639)
@@ -0,0 +1,67 @@
+function assert(b) {
+    if (!b)
+        throw new Error;
+}
+
+function test1() {
+    let x = new Int8Array(1);
+    let y = new Uint8Array(1);
+    x[0] = -1;
+    y.set(x);
+    assert(y[0] === 255);
+}
+test1();
+
+function test2() {
+    let x = new Int8Array(1);
+    let y = new Uint8Array(1);
+    y[0] = 255;
+    x.set(y);
+    assert(x[0] === -1);
+}
+test2();
+
+function test3() {
+    let x = new Int16Array(1);
+    let y = new Uint16Array(1);
+    x[0] = -1;
+    y.set(x);
+    assert(y[0] === 65535);
+}
+test3();
+
+function test4() {
+    let x = new Int16Array(1);
+    let y = new Uint16Array(1);
+    y[0] = 65535;
+    x.set(y);
+    assert(x[0] === -1);
+}
+test4();
+
+function test5() {
+    let x = new Int32Array(1);
+    let y = new Uint32Array(1);
+    x[0] = -1;
+    y.set(x);
+    assert(y[0] === 4294967295);
+}
+test5();
+
+function test6() {
+    let x = new Int32Array(1);
+    let y = new Uint32Array(1);
+    y[0] = 4294967295;
+    x.set(y);
+    assert(x[0] === -1);
+}
+test6();
+
+function test7() {
+    let x = new Uint8ClampedArray(1);
+    let y = new Int8Array(1);
+    x[0] = 255;
+    y.set(x);
+    assert(y[0] === -1);
+}
+test7();

Modified: trunk/LayoutTests/ChangeLog (286638 => 286639)


--- trunk/LayoutTests/ChangeLog	2021-12-08 02:49:51 UTC (rev 286638)
+++ trunk/LayoutTests/ChangeLog	2021-12-08 03:59:13 UTC (rev 286639)
@@ -1,3 +1,13 @@
+2021-12-07  Saam Barati  <[email protected]>
+
+        TypedArray prototype set should go down the fast path when using non clamped integer types of the same byte size
+        https://bugs.webkit.org/show_bug.cgi?id=233905
+
+        Reviewed by Keith Miller.
+
+        * js/script-tests/typedarray-set-overlapping-elements-of-same-size.js:
+        * js/typedarray-set-overlapping-elements-of-same-size-expected.txt:
+
 2021-12-07  Yoshiaki Jitsukawa  <[email protected]>
 
         Support Animated JPEG-XL images

Modified: trunk/LayoutTests/js/script-tests/typedarray-set-overlapping-elements-of-same-size.js (286638 => 286639)


--- trunk/LayoutTests/js/script-tests/typedarray-set-overlapping-elements-of-same-size.js	2021-12-08 02:49:51 UTC (rev 286638)
+++ trunk/LayoutTests/js/script-tests/typedarray-set-overlapping-elements-of-same-size.js	2021-12-08 03:59:13 UTC (rev 286639)
@@ -18,6 +18,6 @@
     return array;
 }
 
-shouldBe("foo(10)", "[42,42,42,42,42,42,42,42,42,42,42]");
+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]");
 

Modified: trunk/LayoutTests/js/typedarray-set-overlapping-elements-of-same-size-expected.txt (286638 => 286639)


--- trunk/LayoutTests/js/typedarray-set-overlapping-elements-of-same-size-expected.txt	2021-12-08 02:49:51 UTC (rev 286638)
+++ trunk/LayoutTests/js/typedarray-set-overlapping-elements-of-same-size-expected.txt	2021-12-08 03:59:13 UTC (rev 286639)
@@ -3,7 +3,7 @@
 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 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
 

Modified: trunk/Source/_javascript_Core/ChangeLog (286638 => 286639)


--- trunk/Source/_javascript_Core/ChangeLog	2021-12-08 02:49:51 UTC (rev 286638)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-12-08 03:59:13 UTC (rev 286639)
@@ -1,3 +1,20 @@
+2021-12-07  Saam Barati  <[email protected]>
+
+        TypedArray prototype set should go down the fast path when using non clamped integer types of the same byte size
+        https://bugs.webkit.org/show_bug.cgi?id=233905
+
+        Reviewed by Keith Miller.
+
+        We can use memmove in this scenario because the bitpattern of the
+        data between the signed and unsigned values will be the same.
+
+        This patch also fixes a bug where we were looking at the wrong
+        pointer when determining to do a forward or backwards loop in
+        our memmove. We were looking at the vector instead of vector+offset.
+
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView<Adaptor>::set):
+
 2021-12-07  Ross Kirsling  <[email protected]>
 
         [JSC] Add LLInt IC for try_get_by_id of own cacheable value

Modified: trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h (286638 => 286639)


--- trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h	2021-12-08 02:49:51 UTC (rev 286638)
+++ trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h	2021-12-08 03:59:13 UTC (rev 286639)
@@ -216,7 +216,7 @@
     // Handle cases (1) and (2A).
     if (!hasArrayBuffer() || !other->hasArrayBuffer()
         || existingBuffer() != other->existingBuffer()
-        || (elementSize == otherElementSize && vector() <= other->vector())
+        || (elementSize == otherElementSize && (static_cast<void*>(typedVector() + offset) <= static_cast<void*>(other->typedVector() + otherOffset)))
         || type == CopyType::LeftToRight) {
         for (size_t i = 0; i < length; ++i) {
             setIndexQuicklyToNativeValue(
@@ -255,34 +255,34 @@
     VM& vm = globalObject->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    auto memmoveFastPath = [&] (auto* other) {
+    auto memmoveFastPath = [&] (JSArrayBufferView* other) {
         // The super fast case: we can just memmove since we're the same underlying storage type.
         length = std::min(length, other->length());
         
-        RELEASE_ASSERT(other->canAccessRangeQuickly(objectOffset, length));
         bool success = validateRange(globalObject, offset, length);
         EXCEPTION_ASSERT(!scope.exception() == success);
         if (!success)
             return false;
 
-        RELEASE_ASSERT((std::is_same_v<decltype(typedVector()), decltype(other->typedVector())>));
-        memmove(typedVector() + offset, other->typedVector() + objectOffset, length * elementSize);
+        RELEASE_ASSERT(JSC::elementSize(Adaptor::typeValue) == JSC::elementSize(other->classInfo(vm)->typedArrayStorageType));
+        memmove(typedVector() + offset, bitwise_cast<typename Adaptor::Type*>(other->vector()) + objectOffset, length * elementSize);
         return true;
     };
 
     const ClassInfo* ci = object->classInfo(vm);
     if (ci->typedArrayStorageType == Adaptor::typeValue)
-        return memmoveFastPath(jsCast<JSGenericTypedArrayView*>(object));
+        return memmoveFastPath(jsCast<JSArrayBufferView*>(object));
 
     auto isSomeUint8 = [] (TypedArrayType type) {
         return type == TypedArrayType::TypeUint8 || type == TypedArrayType::TypeUint8Clamped;
     };
-    if (isSomeUint8(ci->typedArrayStorageType) && isSomeUint8(Adaptor::typeValue)) {
-        if (ci->typedArrayStorageType == TypedArrayType::TypeUint8)
-            return memmoveFastPath(jsCast<JSGenericTypedArrayView<Uint8Adaptor>*>(object));
-        return memmoveFastPath(jsCast<JSGenericTypedArrayView<Uint8ClampedAdaptor>*>(object));
-    }
-    
+
+    if (isSomeUint8(ci->typedArrayStorageType) && isSomeUint8(Adaptor::typeValue))
+        return memmoveFastPath(jsCast<JSArrayBufferView*>(object));
+
+    if (isInt(Adaptor::typeValue) && isInt(ci->typedArrayStorageType) && !isClamped(Adaptor::typeValue) && JSC::elementSize(Adaptor::typeValue) == JSC::elementSize(ci->typedArrayStorageType))
+        return memmoveFastPath(jsCast<JSArrayBufferView*>(object));
+
     switch (ci->typedArrayStorageType) {
     case TypeInt8:
         RELEASE_AND_RETURN(scope, setWithSpecificType<Int8Adaptor>(
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to