[array] Replace JS Array.p.reverse with a Torque implementation
This CL adds a baseline implementation for Array.p.reverse in Torque, as well as fastpaths for PACKED elements kinds. Support for sparse JSArrays was removed. R=jgruber@chromium.org, petermarshall@chromium.org Bug: v8:7624 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: I12900fbbb44746f1c5d36b78be826e14b88b4f69 Reviewed-on: https://chromium-review.googlesource.com/1185600 Commit-Queue: Simon Zünd <szuend@google.com> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#55369}
This commit is contained in:
parent
8093b4f313
commit
837fec91a4
1
BUILD.gn
1
BUILD.gn
@ -887,6 +887,7 @@ torque_files = [
|
||||
"src/builtins/array.tq",
|
||||
"src/builtins/array-copywithin.tq",
|
||||
"src/builtins/array-foreach.tq",
|
||||
"src/builtins/array-reverse.tq",
|
||||
"src/builtins/typed-array.tq",
|
||||
"src/builtins/data-view.tq",
|
||||
"test/torque/test-torque.tq",
|
||||
|
@ -1735,6 +1735,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
0, false);
|
||||
SimpleInstallFunction(isolate_, proto, "push",
|
||||
Builtins::kArrayPrototypePush, 1, false);
|
||||
SimpleInstallFunction(isolate_, proto, "reverse",
|
||||
Builtins::kArrayPrototypeReverse, 0, false);
|
||||
SimpleInstallFunction(isolate_, proto, "shift",
|
||||
Builtins::kArrayPrototypeShift, 0, false);
|
||||
SimpleInstallFunction(isolate_, proto, "unshift", Builtins::kArrayUnshift,
|
||||
|
179
src/builtins/array-reverse.tq
Normal file
179
src/builtins/array-reverse.tq
Normal file
@ -0,0 +1,179 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
module array {
|
||||
macro LoadElement<ElementsAccessor : type, T : type>(
|
||||
elements: FixedArrayBase, index: Smi): T;
|
||||
|
||||
LoadElement<FastPackedSmiElements, Smi>(
|
||||
elements: FixedArrayBase, index: Smi): Smi {
|
||||
const elems: FixedArray = unsafe_cast<FixedArray>(elements);
|
||||
return unsafe_cast<Smi>(elems[index]);
|
||||
}
|
||||
|
||||
LoadElement<FastPackedObjectElements, Object>(
|
||||
elements: FixedArrayBase, index: Smi): Object {
|
||||
const elems: FixedArray = unsafe_cast<FixedArray>(elements);
|
||||
return elems[index];
|
||||
}
|
||||
|
||||
LoadElement<FastPackedDoubleElements, float64>(
|
||||
elements: FixedArrayBase, index: Smi): float64 {
|
||||
try {
|
||||
const elems: FixedDoubleArray = unsafe_cast<FixedDoubleArray>(elements);
|
||||
return LoadDoubleWithHoleCheck(elems, index) otherwise Hole;
|
||||
}
|
||||
label Hole {
|
||||
// This macro is only used for PACKED_DOUBLE, loading the hole should
|
||||
// be impossible.
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
macro StoreElement<ElementsAccessor : type, T : type>(
|
||||
elements: FixedArrayBase, index: Smi, value: T);
|
||||
|
||||
StoreElement<FastPackedSmiElements, Smi>(
|
||||
elements: FixedArrayBase, index: Smi, value: Smi) {
|
||||
const elems: FixedArray = unsafe_cast<FixedArray>(elements);
|
||||
StoreFixedArrayElementSmi(elems, index, value, SKIP_WRITE_BARRIER);
|
||||
}
|
||||
|
||||
StoreElement<FastPackedObjectElements, Object>(
|
||||
elements: FixedArrayBase, index: Smi, value: Object) {
|
||||
const elems: FixedArray = unsafe_cast<FixedArray>(elements);
|
||||
elems[index] = value;
|
||||
}
|
||||
|
||||
StoreElement<FastPackedDoubleElements, float64>(
|
||||
elements: FixedArrayBase, index: Smi, value: float64) {
|
||||
const elems: FixedDoubleArray = unsafe_cast<FixedDoubleArray>(elements);
|
||||
|
||||
assert(value == Float64SilenceNaN(value));
|
||||
StoreFixedDoubleArrayElementWithSmiIndex(elems, index, value);
|
||||
}
|
||||
|
||||
// Fast-path for all PACKED_* elements kinds. These do not need to check
|
||||
// whether a property is present, so we can simply swap them using fast
|
||||
// FixedArray loads/stores.
|
||||
macro FastPackedArrayReverse<Accessor : type, T : type>(
|
||||
elements: FixedArrayBase, length: Smi) {
|
||||
let lower: Smi = 0;
|
||||
let upper: Smi = length - 1;
|
||||
|
||||
while (lower < upper) {
|
||||
const lower_value: T = LoadElement<Accessor, T>(elements, lower);
|
||||
const upper_value: T = LoadElement<Accessor, T>(elements, upper);
|
||||
StoreElement<Accessor, T>(elements, lower, upper_value);
|
||||
StoreElement<Accessor, T>(elements, upper, lower_value);
|
||||
++lower;
|
||||
--upper;
|
||||
}
|
||||
}
|
||||
|
||||
macro GenericArrayReverse(context: Context, receiver: Object): Object {
|
||||
// 1. Let O be ? ToObject(this value).
|
||||
const object: JSReceiver = ToObject_Inline(context, receiver);
|
||||
|
||||
// 2. Let len be ? ToLength(? Get(O, "length")).
|
||||
const length: Number = GetLengthProperty(context, object);
|
||||
|
||||
// 3. Let middle be floor(len / 2).
|
||||
// 4. Let lower be 0.
|
||||
// 5. Repeat, while lower != middle.
|
||||
// a. Let upper be len - lower - 1.
|
||||
|
||||
// Instead of calculating the middle value, we simply initialize upper
|
||||
// with len - 1 and decrement it after each iteration.
|
||||
let lower: Number = 0;
|
||||
let upper: Number = length - 1;
|
||||
|
||||
while (lower < upper) {
|
||||
let lower_value: Object = Undefined;
|
||||
let upper_value: Object = Undefined;
|
||||
|
||||
// b. Let upperP be ! ToString(upper).
|
||||
// c. Let lowerP be ! ToString(lower).
|
||||
// d. Let lowerExists be ? HasProperty(O, lowerP).
|
||||
const lower_exists: Boolean = HasProperty(context, object, lower);
|
||||
|
||||
// e. If lowerExists is true, then.
|
||||
if (lower_exists == True) {
|
||||
// i. Let lowerValue be ? Get(O, lowerP).
|
||||
lower_value = GetProperty(context, object, lower);
|
||||
}
|
||||
|
||||
// f. Let upperExists be ? HasProperty(O, upperP).
|
||||
const upper_exists: Boolean = HasProperty(context, object, upper);
|
||||
|
||||
// g. If upperExists is true, then.
|
||||
if (upper_exists == True) {
|
||||
// i. Let upperValue be ? Get(O, upperP).
|
||||
upper_value = GetProperty(context, object, upper);
|
||||
}
|
||||
|
||||
// h. If lowerExists is true and upperExists is true, then
|
||||
if (lower_exists == True && upper_exists == True) {
|
||||
// i. Perform ? Set(O, lowerP, upperValue, true).
|
||||
SetProperty(context, object, lower, upper_value);
|
||||
|
||||
// ii. Perform ? Set(O, upperP, lowerValue, true).
|
||||
SetProperty(context, object, upper, lower_value);
|
||||
} else if (lower_exists == False && upper_exists == True) {
|
||||
// i. Perform ? Set(O, lowerP, upperValue, true).
|
||||
SetProperty(context, object, lower, upper_value);
|
||||
|
||||
// ii. Perform ? DeletePropertyOrThrow(O, upperP).
|
||||
DeleteProperty(context, object, upper, kStrict);
|
||||
} else if (lower_exists == True && upper_exists == False) {
|
||||
// i. Perform ? DeletePropertyOrThrow(O, lowerP).
|
||||
DeleteProperty(context, object, lower, kStrict);
|
||||
|
||||
// ii. Perform ? Set(O, upperP, lowerValue, true).
|
||||
SetProperty(context, object, upper, lower_value);
|
||||
}
|
||||
|
||||
// l. Increase lower by 1.
|
||||
++lower;
|
||||
--upper;
|
||||
}
|
||||
|
||||
// 6. Return O.
|
||||
return object;
|
||||
}
|
||||
|
||||
macro TryFastPackedArrayReverse(receiver: Object) labels Slow {
|
||||
const array: JSArray = cast<JSArray>(receiver) otherwise Slow;
|
||||
const map: Map = array.map;
|
||||
|
||||
if (!IsExtensibleMap(map)) goto Slow;
|
||||
if (array.elements.map == kCOWMap) goto Slow;
|
||||
|
||||
const kind: ElementsKind = map.elements_kind;
|
||||
if (kind == PACKED_SMI_ELEMENTS) {
|
||||
FastPackedArrayReverse<FastPackedSmiElements, Smi>(
|
||||
array.elements, array.length_fast);
|
||||
} else if (kind == PACKED_ELEMENTS) {
|
||||
FastPackedArrayReverse<FastPackedObjectElements, Object>(
|
||||
array.elements, array.length_fast);
|
||||
} else if (kind == PACKED_DOUBLE_ELEMENTS) {
|
||||
FastPackedArrayReverse<FastPackedDoubleElements, float64>(
|
||||
array.elements, array.length_fast);
|
||||
} else {
|
||||
goto Slow;
|
||||
}
|
||||
}
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-array.prototype.reverse
|
||||
javascript builtin ArrayPrototypeReverse(
|
||||
context: Context, receiver: Object, ...arguments): Object {
|
||||
try {
|
||||
TryFastPackedArrayReverse(receiver) otherwise Baseline;
|
||||
return receiver;
|
||||
}
|
||||
label Baseline {
|
||||
return GenericArrayReverse(context, receiver);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,17 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
module array {
|
||||
// Naming convention from elements.cc. We have a similar intent but implement
|
||||
// fastpaths using generics instead of using a class hierarchy for elements
|
||||
// kinds specific implementations.
|
||||
type GenericElementsAccessor;
|
||||
type FastPackedSmiElements;
|
||||
type FastPackedObjectElements;
|
||||
type FastPackedDoubleElements;
|
||||
type FastSmiOrObjectElements;
|
||||
type FastDoubleElements;
|
||||
type DictionaryElements;
|
||||
|
||||
macro GetLengthProperty(context: Context, o: Object): Number {
|
||||
if (BranchIfFastJSArray(o, context)) {
|
||||
let a: JSArray = unsafe_cast<JSArray>(o);
|
||||
|
@ -817,6 +817,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
|
||||
case Builtins::kArrayIteratorPrototypeNext:
|
||||
case Builtins::kArrayPrototypePop:
|
||||
case Builtins::kArrayPrototypePush:
|
||||
case Builtins::kArrayPrototypeReverse:
|
||||
case Builtins::kArrayPrototypeShift:
|
||||
case Builtins::kArraySplice:
|
||||
case Builtins::kArrayUnshift:
|
||||
|
100
src/js/array.js
100
src/js/array.js
@ -408,106 +408,6 @@ DEFINE_METHOD(
|
||||
);
|
||||
|
||||
|
||||
// For implementing reverse() on large, sparse arrays.
|
||||
function SparseReverse(array, len) {
|
||||
var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
|
||||
var high_counter = keys.length - 1;
|
||||
var low_counter = 0;
|
||||
while (low_counter <= high_counter) {
|
||||
var i = keys[low_counter];
|
||||
var j = keys[high_counter];
|
||||
|
||||
var j_complement = len - j - 1;
|
||||
var low, high;
|
||||
|
||||
if (j_complement <= i) {
|
||||
high = j;
|
||||
while (keys[--high_counter] == j) { }
|
||||
low = j_complement;
|
||||
}
|
||||
if (j_complement >= i) {
|
||||
low = i;
|
||||
while (keys[++low_counter] == i) { }
|
||||
high = len - i - 1;
|
||||
}
|
||||
|
||||
var current_i = array[low];
|
||||
if (!IS_UNDEFINED(current_i) || low in array) {
|
||||
var current_j = array[high];
|
||||
if (!IS_UNDEFINED(current_j) || high in array) {
|
||||
array[low] = current_j;
|
||||
array[high] = current_i;
|
||||
} else {
|
||||
array[high] = current_i;
|
||||
delete array[low];
|
||||
}
|
||||
} else {
|
||||
var current_j = array[high];
|
||||
if (!IS_UNDEFINED(current_j) || high in array) {
|
||||
array[low] = current_j;
|
||||
delete array[high];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function PackedArrayReverse(array, len) {
|
||||
var j = len - 1;
|
||||
for (var i = 0; i < j; i++, j--) {
|
||||
var current_i = array[i];
|
||||
var current_j = array[j];
|
||||
array[i] = current_j;
|
||||
array[j] = current_i;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
function GenericArrayReverse(array, len) {
|
||||
var j = len - 1;
|
||||
for (var i = 0; i < j; i++, j--) {
|
||||
if (i in array) {
|
||||
var current_i = array[i];
|
||||
if (j in array) {
|
||||
var current_j = array[j];
|
||||
array[i] = current_j;
|
||||
array[j] = current_i;
|
||||
} else {
|
||||
array[j] = current_i;
|
||||
delete array[i];
|
||||
}
|
||||
} else {
|
||||
if (j in array) {
|
||||
var current_j = array[j];
|
||||
array[i] = current_j;
|
||||
delete array[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
DEFINE_METHOD(
|
||||
GlobalArray.prototype,
|
||||
reverse() {
|
||||
var array = TO_OBJECT(this);
|
||||
var len = TO_LENGTH(array.length);
|
||||
var isArray = IS_ARRAY(array);
|
||||
|
||||
if (UseSparseVariant(array, len, isArray, len)) {
|
||||
%NormalizeElements(array);
|
||||
SparseReverse(array, len);
|
||||
return array;
|
||||
} else if (isArray && %_HasFastPackedElements(array)) {
|
||||
return PackedArrayReverse(array, len);
|
||||
} else {
|
||||
return GenericArrayReverse(array, len);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
function ArrayShiftFallback() {
|
||||
var array = TO_OBJECT(this);
|
||||
var len = TO_LENGTH(array.length);
|
||||
|
70
test/mjsunit/array-reverse.js
Normal file
70
test/mjsunit/array-reverse.js
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
assertArrayEquals([], [].reverse());
|
||||
assertArrayEquals([8, 6, 4, 2], [2, 4, 6, 8].reverse());
|
||||
assertArrayEquals([0.8, 0.6, 0.4], [0.4, 0.6, 0.8].reverse());
|
||||
assertArrayEquals(["str4", "str3", "str2"], ["str2", "str3", "str4"].reverse());
|
||||
|
||||
assertArrayEquals([4,3,,1], [1,,3,4].reverse());
|
||||
assertArrayEquals([4,,2,1], [1,2,,4].reverse());
|
||||
assertArrayEquals([5,,3,,1], [1,,3,,5].reverse());
|
||||
|
||||
function TestReverseWithObject() {
|
||||
let obj = { length: 5 };
|
||||
obj[0] = "foo";
|
||||
obj[3] = "bar";
|
||||
Array.prototype.reverse.call(obj);
|
||||
|
||||
assertArrayEquals([,"bar",,,"foo"], obj);
|
||||
}
|
||||
TestReverseWithObject();
|
||||
|
||||
function TestReverseWithPrototypeChain() {
|
||||
let proto = { 0: "foo", 19: "bar" };
|
||||
let obj = { length: 20, 5: "foobar", __proto__: proto };
|
||||
Array.prototype.reverse.call(obj);
|
||||
|
||||
assertEquals("bar", obj[0]);
|
||||
assertEquals("foobar", obj[14]);
|
||||
assertEquals("foo", obj[19]);
|
||||
}
|
||||
TestReverseWithPrototypeChain();
|
||||
|
||||
function TestReverseWithTypedArrays() {
|
||||
const constructors = [
|
||||
Uint8Array,
|
||||
Int8Array,
|
||||
Uint16Array,
|
||||
Int16Array,
|
||||
Uint32Array,
|
||||
Int32Array,
|
||||
Uint8ClampedArray,
|
||||
Float32Array,
|
||||
Float64Array
|
||||
];
|
||||
|
||||
for (const constructor of constructors) {
|
||||
const array_odd = new constructor([1, 2, 3]);
|
||||
Array.prototype.reverse.call(array_odd);
|
||||
assertArrayEquals([3, 2, 1], array_odd, constructor);
|
||||
|
||||
const array_even = new constructor([1, 2, 3, 4]);
|
||||
Array.prototype.reverse.call(array_even);
|
||||
assertArrayEquals([4, 3, 2, 1], array_even, constructor);
|
||||
|
||||
// Array.prototype.reverse respects shadowing length on TypedArrays.
|
||||
const array = new constructor([1, 2, 3, 4]);
|
||||
Object.defineProperty(array, 'length', {value: 2});
|
||||
Array.prototype.reverse.call(array);
|
||||
|
||||
assertArrayEquals([2, 1], array, constructor);
|
||||
|
||||
const array_shadowed_length = new constructor([1, 2]);
|
||||
Object.defineProperty(array_shadowed_length, 'length', {value: 5});
|
||||
|
||||
assertThrows(() => Array.prototype.reverse.call(array_shadowed_length));
|
||||
}
|
||||
}
|
||||
TestReverseWithTypedArrays();
|
@ -1,43 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Regression test for http://code.google.com/p/v8/issues/detail?id=685.
|
||||
//
|
||||
// Test that keyed load IC generic stub uses unsigned comparison for
|
||||
// for the length field of arrays.
|
||||
//
|
||||
// The test passes if it does not crash.
|
||||
|
||||
function test() {
|
||||
var N = 0xFFFFFFFF;
|
||||
var a = [];
|
||||
a[N - 1] = 0;
|
||||
a[N - 2] = 1;
|
||||
a.reverse();
|
||||
}
|
||||
|
||||
test();
|
@ -1,131 +0,0 @@
|
||||
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* @fileoverview Test reverse on small * and large arrays.
|
||||
*/
|
||||
|
||||
var VERYLARGE = 4000000000;
|
||||
|
||||
// Nicer for firefox 1.5. Unless you uncomment the following line,
|
||||
// smjs will appear to hang on this file.
|
||||
//var VERYLARGE = 40000;
|
||||
|
||||
|
||||
// Simple test of reverse on sparse array.
|
||||
var a = [];
|
||||
a.length = 2000;
|
||||
a[15] = 'a';
|
||||
a[30] = 'b';
|
||||
Array.prototype[30] = 'B'; // Should be hidden by a[30].
|
||||
a[40] = 'c';
|
||||
a[50] = 'deleted';
|
||||
delete a[50]; // Should leave no trace once deleted.
|
||||
a[1959] = 'd'; // Swapped with a[40] when reversing.
|
||||
a[1999] = 'e';
|
||||
assertEquals("abcde", a.join(''));
|
||||
a.reverse();
|
||||
delete Array.prototype[30];
|
||||
assertEquals("edcba", a.join(''));
|
||||
|
||||
|
||||
|
||||
var seed = 43;
|
||||
|
||||
// CONG pseudo random number generator. Used for fuzzing the sparse array
|
||||
// reverse code.
|
||||
function DoOrDont() {
|
||||
seed = (69069 * seed + 1234567) % 0x100000000;
|
||||
return (seed & 0x100000) != 0;
|
||||
}
|
||||
|
||||
var sizes = [140, 40000, VERYLARGE];
|
||||
var poses = [0, 10, 50, 69];
|
||||
|
||||
|
||||
// Fuzzing test of reverse on sparse array.
|
||||
for (var iterations = 0; iterations < 20; iterations++) {
|
||||
for (var size_pos = 0; size_pos < sizes.length; size_pos++) {
|
||||
var size = sizes[size_pos];
|
||||
|
||||
var to_delete = [];
|
||||
|
||||
var a;
|
||||
// Make sure we test both array-backed and hash-table backed
|
||||
// arrays.
|
||||
if (size < 1000) {
|
||||
a = new Array(size);
|
||||
} else {
|
||||
a = new Array();
|
||||
a.length = size;
|
||||
}
|
||||
|
||||
var expected = '';
|
||||
var expected_reversed = '';
|
||||
|
||||
for (var pos_pos = 0; pos_pos < poses.length; pos_pos++) {
|
||||
var pos = poses[pos_pos];
|
||||
var letter = String.fromCharCode(97 + pos_pos);
|
||||
if (DoOrDont()) {
|
||||
a[pos] = letter;
|
||||
expected += letter;
|
||||
expected_reversed = letter + expected_reversed;
|
||||
} else if (DoOrDont()) {
|
||||
Array.prototype[pos] = letter;
|
||||
expected += letter;
|
||||
expected_reversed = letter + expected_reversed;
|
||||
to_delete.push(pos);
|
||||
}
|
||||
}
|
||||
var expected2 = '';
|
||||
var expected_reversed2 = '';
|
||||
for (var pos_pos = poses.length - 1; pos_pos >= 0; pos_pos--) {
|
||||
var letter = String.fromCharCode(110 + pos_pos);
|
||||
var pos = size - poses[pos_pos] - 1;
|
||||
if (DoOrDont()) {
|
||||
a[pos] = letter;
|
||||
expected2 += letter;
|
||||
expected_reversed2 = letter + expected_reversed2;
|
||||
} else if (DoOrDont()) {
|
||||
Array.prototype[pos] = letter;
|
||||
expected2 += letter;
|
||||
expected_reversed2 = letter + expected_reversed2;
|
||||
to_delete.push(pos);
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(expected + expected2, a.join(''), 'join' + size);
|
||||
a.reverse();
|
||||
|
||||
while (to_delete.length != 0) {
|
||||
var pos = to_delete.pop();
|
||||
delete(Array.prototype[pos]);
|
||||
}
|
||||
|
||||
assertEquals(expected_reversed2 + expected_reversed, a.join(''), 'reverse then join' + size);
|
||||
}
|
||||
}
|
@ -517,7 +517,6 @@
|
||||
|
||||
# https://bugs.chromium.org/p/v8/issues/detail?id=6538
|
||||
'built-ins/Array/prototype/unshift/throws-if-integer-limit-exceeded': [SKIP],
|
||||
'built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-proxy': [FAIL],
|
||||
'built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit': [FAIL],
|
||||
'built-ins/Array/prototype/splice/throws-if-integer-limit-exceeded': [SKIP],
|
||||
|
||||
|
9
third_party/v8/builtins/array-sort.tq
vendored
9
third_party/v8/builtins/array-sort.tq
vendored
@ -14,9 +14,6 @@
|
||||
// https://github.com/python/cpython/blob/master/Objects/listsort.txt
|
||||
|
||||
module array {
|
||||
// Naming convention from elements.cc. We have a similar intent but implement
|
||||
// fastpaths using generics instead of using a class hierarchy for elements
|
||||
// kinds specific implementations.
|
||||
// All accessors bail to the GenericElementsAccessor if assumptions checked
|
||||
// by "CanUseSameAccessor<>" are violated:
|
||||
// Generic <- FastPackedSmi
|
||||
@ -27,12 +24,6 @@ module array {
|
||||
// The only exception is TempArrayElements, since it does not describe the
|
||||
// "elements" of the receiver, but instead is used as an "adaptor" so
|
||||
// GallopLeft/GallopRight can be reused with the temporary array.
|
||||
type GenericElementsAccessor;
|
||||
type FastPackedSmiElements;
|
||||
type FastSmiOrObjectElements;
|
||||
type FastDoubleElements;
|
||||
type DictionaryElements;
|
||||
|
||||
const kGenericElementsAccessorId: Smi = 0;
|
||||
const kFastElementsAccessorId: Smi = 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user