Skip to content

Commit 9bbad8a

Browse files
committed
[JSC] TypedArray change-array-by-copy should be C++
https://bugs.webkit.org/show_bug.cgi?id=243162 Reviewed by Alexey Shvayka and Ross Kirsling. This patch implements TypedArray change-array-by-copy in C++ to get performance boost. TypedArray has a lot of characteristics of non-dynamic behavior. Since it is typed too, then we can easily write super fast C++ implementations for these methods. This patch keeps toSorted in JS while large part of it is implemented in C++ already. And we also migrate subarray from JS to C++ since we have fast speciesConstruct now. ToT Patched typed-array-to-sorted-hot 131.0737+-0.0586 ^ 79.5521+-0.1355 ^ definitely 1.6476x faster typed-array-subarray-hot 4.5564+-0.2404 ^ 3.5946+-0.0116 ^ definitely 1.2676x faster typed-array-to-reversed-hot 93.7245+-0.1785 ^ 28.5393+-0.1813 ^ definitely 3.2841x faster typed-array-with-hot 78.6775+-0.2573 ^ 10.2874+-0.0542 ^ definitely 7.6479x faster * JSTests/microbenchmarks/typed-array-subarray-hot.js: Added. * JSTests/microbenchmarks/typed-array-to-reversed-hot.js: Added. * JSTests/microbenchmarks/typed-array-to-sorted-hot.js: Added. * Source/JavaScriptCore/builtins/BuiltinNames.h: * Source/JavaScriptCore/builtins/TypedArrayPrototype.js: (subarray): Deleted. (toReversed): Deleted. * Source/JavaScriptCore/bytecode/LinkTimeConstant.h: * Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h: (JSC::speciesConstruct): (JSC::genericTypedArrayViewProtoFuncToReversed): (JSC::genericTypedArrayViewProtoFuncToSorted): (JSC::genericTypedArrayViewProtoFuncSlice): (JSC::genericTypedArrayViewProtoFuncSubarray): (JSC::genericTypedArrayViewPrivateFuncSubarrayCreate): Deleted. * Source/JavaScriptCore/runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::init): * Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.cpp: (JSC::JSC_DEFINE_HOST_FUNCTION): (JSC::JSTypedArrayViewPrototype::finishCreation): * Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.h: Canonical link: https://commits.webkit.org/252891@main
1 parent 9b5aa3c commit 9bbad8a

14 files changed

Lines changed: 252 additions & 154 deletions
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
var typedArray = new Uint8Array(1024);
2+
typedArray.fill(253);
3+
var output = typedArray.subarray();
4+
for (let i = 0; i < 100000; i++) {
5+
output = output.subarray();
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
var typedArray = new Uint8Array(1024);
2+
typedArray.fill(253);
3+
var output = typedArray.toReversed();
4+
for (let i = 0; i < 100000; i++) {
5+
output = output.toReversed();
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
var typedArray = new Uint8Array(1024);
2+
typedArray.fill(253);
3+
var output = typedArray.toSorted();
4+
for (let i = 0; i < 100000; i++) {
5+
output = output.toSorted();
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
var typedArray = new Uint8Array(1024);
2+
typedArray.fill(253);
3+
var output = typedArray.with(0, 1);
4+
for (let i = 0; i < 100000; i++) {
5+
output = output.with(i & 1023, i);
6+
}

‎Source/JavaScriptCore/builtins/ArrayPrototype.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -818,12 +818,12 @@ function toReversed()
818818
return result;
819819
}
820820

821-
function toSorted(comparefn)
821+
function toSorted(comparator)
822822
{
823823
"use strict";
824824

825825
// Step 1.
826-
if (comparefn !== @undefined && !@isCallable(comparefn))
826+
if (comparator !== @undefined && !@isCallable(comparator))
827827
@throwTypeError("Array.prototype.toSorted requires the comparator argument to be a function or undefined");
828828

829829
// Step 2.
@@ -840,7 +840,7 @@ function toSorted(comparefn)
840840
@putByValDirect(result, k, array[k]);
841841

842842
// Step 6.
843-
@arraySort.@call(result, comparefn);
843+
@arraySort.@call(result, comparator);
844844

845845
return result;
846846
}

‎Source/JavaScriptCore/builtins/BuiltinNames.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ namespace JSC {
7373
macro(Map) \
7474
macro(throwTypeErrorFunction) \
7575
macro(typedArrayLength) \
76+
macro(typedArrayClone) \
7677
macro(typedArrayContentType) \
7778
macro(typedArraySort) \
7879
macro(typedArrayGetOriginalConstructor) \
79-
macro(typedArraySubarrayCreate) \
8080
macro(BuiltinLog) \
8181
macro(BuiltinDescribe) \
8282
macro(homeObject) \

‎Source/JavaScriptCore/builtins/TypedArrayPrototype.js‎

Lines changed: 15 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ function typedArrayMergeSort(array, valueCount, comparator)
213213
}
214214
}
215215

216-
@linkTimeConstant
217216
function sort(comparator)
218217
{
219218
"use strict";
@@ -237,23 +236,6 @@ function sort(comparator)
237236
return this;
238237
}
239238

240-
function subarray(begin, end)
241-
{
242-
"use strict";
243-
244-
if (!@isTypedArrayView(this))
245-
@throwTypeError("|this| should be a typed array view");
246-
247-
var start = @toIntegerOrInfinity(begin);
248-
var finish;
249-
if (end !== @undefined)
250-
finish = @toIntegerOrInfinity(end);
251-
252-
var constructor = @typedArraySpeciesConstructor(this);
253-
254-
return @typedArraySubarrayCreate.@call(this, start, finish, constructor);
255-
}
256-
257239
function reduce(callback /* [, initialValue] */)
258240
{
259241
// 22.2.3.19
@@ -393,85 +375,28 @@ function at(index)
393375
return (k >= 0 && k < length) ? this[k] : @undefined;
394376
}
395377

396-
function toReversed()
397-
{
398-
"use strict";
399-
400-
// Step 2-3.
401-
var length = @typedArrayLength(this);
402-
403-
// Step 4.
404-
var constructor = @typedArrayGetOriginalConstructor(this);
405-
var result = new constructor(length);
406-
407-
// Step 5-6.
408-
for (var k = 0; k < length; k++) {
409-
var fromValue = this[length - k - 1];
410-
result[k] = fromValue;
411-
}
412-
413-
return result;
414-
}
415-
416-
function toSorted(comparefn)
378+
function toSorted(comparator)
417379
{
418380
"use strict";
419381

420382
// Step 1.
421-
if (comparefn !== @undefined && !@isCallable(comparefn))
422-
@throwTypeError("TypedArray.prototype.toSorted requires the comparefn argument to be a function or undefined");
423-
424-
// Step 5.
425-
var length = @typedArrayLength(this);
426-
427-
// Step 6.
428-
var constructor = @typedArrayGetOriginalConstructor(this);
429-
var result = new constructor(length);
430-
431-
// Step 11.
432-
for (var k = 0; k < length; k++)
433-
result[k] = this[k];
434-
435-
// Step 9.
436-
@sort.@call(result, comparefn);
437-
438-
return result;
439-
}
440-
441-
function with(index, value)
442-
{
443-
"use strict";
444-
445-
// Step 2-3.
446-
var length = @typedArrayLength(this);
447-
448-
// Step 4.
449-
var relativeIndex = @toIntegerOrInfinity(index);
450-
var actualIndex;
451-
452-
// Step 5-6.
453-
if (relativeIndex >= 0)
454-
actualIndex = relativeIndex;
455-
else
456-
actualIndex = length + relativeIndex;
383+
if (comparator !== @undefined && !@isCallable(comparator))
384+
@throwTypeError("TypedArray.prototype.toSorted requires the comparator argument to be a function or undefined");
457385

458-
// Step 7.
459-
if (@isDetached(this))
460-
@throwRangeError("TypedArray.prototype.with called on an detached array");
461-
if (actualIndex < 0 || actualIndex >= length)
462-
@throwRangeError("Array index out of range")
386+
var result = @typedArrayClone.@call(this);
463387

464-
// Step 8.
465-
var constructor = @typedArrayGetOriginalConstructor(this);
466-
var result = new constructor(length);
388+
var length = @typedArrayLength(result);
389+
if (length < 2)
390+
return result;
467391

468-
// Step 9-10.
469-
for (var k = 0; k < length; k++) {
470-
if (k == actualIndex)
471-
result[k] = value;
472-
else
473-
result[k] = this[k];
474-
}
392+
// typedArraySort is not safe when the other thread is modifying content. So if |result| is SharedArrayBuffer,
393+
// use JS-implemented sorting.
394+
if (comparator !== @undefined || @isSharedTypedArrayView(result)) {
395+
if (comparator === @undefined)
396+
comparator = @typedArrayDefaultComparator;
397+
@typedArrayMergeSort(result, length, comparator);
398+
} else
399+
@typedArraySort(result);
475400

476401
return result;
477402
}

‎Source/JavaScriptCore/bytecode/LinkTimeConstant.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ class JSGlobalObject;
5050
v(makeTypeError, nullptr) \
5151
v(AggregateError, nullptr) \
5252
v(typedArrayLength, nullptr) \
53+
v(typedArrayClone, nullptr) \
5354
v(typedArrayContentType, nullptr) \
5455
v(typedArrayGetOriginalConstructor, nullptr) \
5556
v(typedArraySort, nullptr) \
5657
v(isTypedArrayView, nullptr) \
5758
v(isSharedTypedArrayView, nullptr) \
5859
v(isDetached, nullptr) \
5960
v(typedArrayDefaultComparator, nullptr) \
60-
v(typedArraySubarrayCreate, nullptr) \
6161
v(isBoundFunction, nullptr) \
6262
v(hasInstanceBoundFunction, nullptr) \
6363
v(instanceOf, nullptr) \

‎Source/JavaScriptCore/runtime/IntlObject.cpp‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,7 @@ const Vector<String>& intlAvailableCalendars()
16021602
}
16031603

16041604
// The AvailableCalendars abstract operation returns a List, ordered as if an Array of the same
1605-
// values had been sorted using %Array.prototype.sort% using undefined as comparefn
1605+
// values had been sorted using %Array.prototype.sort% using undefined as comparator
16061606
std::sort(availableCalendars->begin(), availableCalendars->end(),
16071607
[](const String& a, const String& b) {
16081608
return WTF::codePointCompare(a, b) < 0;
@@ -1676,7 +1676,7 @@ static JSArray* availableCollations(JSGlobalObject* globalObject)
16761676
}
16771677

16781678
// The AvailableCollations abstract operation returns a List, ordered as if an Array of the same
1679-
// values had been sorted using %Array.prototype.sort% using undefined as comparefn
1679+
// values had been sorted using %Array.prototype.sort% using undefined as comparator
16801680
std::sort(elements.begin(), elements.end(),
16811681
[](const String& a, const String& b) {
16821682
return WTF::codePointCompare(a, b) < 0;
@@ -1732,7 +1732,7 @@ static JSArray* availableCurrencies(JSGlobalObject* globalObject)
17321732
}
17331733

17341734
// The AvailableCurrencies abstract operation returns a List, ordered as if an Array of the same
1735-
// values had been sorted using %Array.prototype.sort% using undefined as comparefn
1735+
// values had been sorted using %Array.prototype.sort% using undefined as comparator
17361736
std::sort(elements.begin(), elements.end(),
17371737
[](const String& a, const String& b) {
17381738
return WTF::codePointCompare(a, b) < 0;
@@ -1782,7 +1782,7 @@ static JSArray* availableNumberingSystems(JSGlobalObject* globalObject)
17821782
}
17831783

17841784
// The AvailableNumberingSystems abstract operation returns a List, ordered as if an Array of the same
1785-
// values had been sorted using %Array.prototype.sort% using undefined as comparefn
1785+
// values had been sorted using %Array.prototype.sort% using undefined as comprator
17861786
std::sort(elements.begin(), elements.end(),
17871787
[](const String& a, const String& b) {
17881788
return WTF::codePointCompare(a, b) < 0;
@@ -1840,7 +1840,7 @@ const Vector<String>& intlAvailableTimeZones()
18401840
}
18411841

18421842
// The AvailableTimeZones abstract operation returns a List, ordered as if an Array of the same
1843-
// values had been sorted using %Array.prototype.sort% using undefined as comparefn
1843+
// values had been sorted using %Array.prototype.sort% using undefined as comparator
18441844
std::sort(temporary.begin(), temporary.end(),
18451845
[](const String& a, const String& b) {
18461846
return WTF::codePointCompare(a, b) < 0;

0 commit comments

Comments
 (0)