Commit 540bb0c8 authored by Daniel Ehrenberg's avatar Daniel Ehrenberg Committed by Adam Klein

Implement %TypedArray%.prototype.sort

The sort method of TypedArrays sorts in numerical order by default.
This patch implements sorting based on Arrays and adds a test.
The length of %TypedArray%.prototype.sort, like Array.prototype.sort,
seems to be unspecified in ES6, so this patch lets it have the value
1, to match our interpretation for Array.prototype.sort (though 0
would also be a sensible length).

R=arv@chromium.org
BUG=v8:3578
LOG=Y

Review URL: https://codereview.chromium.org/1148513002

Patch from Daniel Ehrenberg <dehrenberg@chromium.org>.

Cr-Commit-Position: refs/heads/master@{#28494}
parent cc74268d
......@@ -13,6 +13,7 @@ var $arrayUnshift;
var $innerArrayForEach;
var $innerArrayEvery;
var $innerArrayReverse;
var $innerArraySort;
(function(global, shared, exports) {
......@@ -867,9 +868,7 @@ function ArraySplice(start, delete_count) {
}
function ArraySort(comparefn) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
function InnerArraySort(length, comparefn) {
// In-place QuickSort algorithm.
// For short (length <= 22) arrays, insertion sort is used for efficiency.
......@@ -1114,7 +1113,6 @@ function ArraySort(comparefn) {
return first_undefined;
};
var length = TO_UINT32(this.length);
if (length < 2) return this;
var is_array = IS_ARRAY(this);
......@@ -1153,6 +1151,14 @@ function ArraySort(comparefn) {
}
function ArraySort(comparefn) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
var length = TO_UINT32(this.length);
return %_CallFunction(this, length, comparefn, InnerArraySort);
}
// The following functions cannot be made efficient on sparse arrays while
// preserving the semantics, since the calls to the receiver function can add
// or delete elements from the array.
......@@ -1616,5 +1622,6 @@ $arrayUnshift = ArrayUnshift;
$innerArrayForEach = InnerArrayForEach;
$innerArrayEvery = InnerArrayEvery;
$innerArrayReverse = InnerArrayReverse;
$innerArraySort = InnerArraySort;
});
......@@ -100,6 +100,40 @@ function TypedArrayReverse() {
}
function TypedArrayComparefn(x, y) {
if ($isNaN(x) && $isNaN(y)) {
return $isNaN(y) ? 0 : 1;
}
if ($isNaN(x)) {
return 1;
}
if (x === 0 && x === y) {
if (%_IsMinusZero(x)) {
if (!%_IsMinusZero(y)) {
return -1;
}
} else if (%_IsMinusZero(y)) {
return 1;
}
}
return x - y;
}
// ES6 draft 05-18-15, section 22.2.3.25
function TypedArraySort(comparefn) {
if (!%IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
var length = %_TypedArrayGetLength(this);
if (IS_UNDEFINED(comparefn)) {
comparefn = TypedArrayComparefn;
}
return %_CallFunction(this, length, comparefn, $innerArraySort);
}
// ES6 draft 08-24-14, section 22.2.2.2
function TypedArrayOf() {
var length = %_ArgumentsLength();
......@@ -150,7 +184,8 @@ macro EXTEND_TYPED_ARRAY(NAME)
"find", TypedArrayFind,
"findIndex", TypedArrayFindIndex,
"fill", TypedArrayFill,
"reverse", TypedArrayReverse
"reverse", TypedArrayReverse,
"sort", TypedArraySort
]);
endmacro
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-arrays
var typedArrayConstructors = [
Uint8Array,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Uint8ClampedArray,
Float32Array,
Float64Array
];
function assertArrayLikeEquals(value, expected, type) {
assertEquals(value.__proto__, type.prototype);
// Don't test value.length because we mess with that;
// instead in certain callsites we check that length
// is set appropriately.
for (var i = 0; i < expected.length; ++i) {
// Use Object.is to differentiate between +-0
assertSame(expected[i], value[i]);
}
}
for (var constructor of typedArrayConstructors) {
// Test default numerical sorting order
var a = new constructor([100, 7, 45])
assertEquals(a.sort(), a);
assertArrayLikeEquals(a, [7, 45, 100], constructor);
assertEquals(a.length, 3);
// For arrays of floats, certain handling of +-0/NaN
if (constructor === Float32Array || constructor === Float64Array) {
var b = new constructor([+0, -0, NaN, -0, NaN, +0])
b.sort();
assertArrayLikeEquals(b, [-0, -0, +0, +0, NaN, NaN], constructor);
assertEquals(b.length, 6);
}
// Custom sort--backwards
a.sort(function(x, y) { return y - x; });
assertArrayLikeEquals(a, [100, 45, 7], constructor);
// Basic TypedArray method properties:
// Length field is ignored
Object.defineProperty(a, 'length', {value: 1});
assertEquals(a.sort(), a);
assertArrayLikeEquals(a, [7, 45, 100], constructor);
assertEquals(a.length, 1);
// Method doesn't work on other objects
assertThrows(function() { a.sort.call([]); }, TypeError);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment