v8/test/js-perf-test/ArraySort/sort-base.js
Simon Zünd 2b0ac2fb9f [array] Move Array#sort pre-processing to Torque
This CL removes the "PrepareElementsForSort" runtime function, and
replaces it with a simpler version in Torque. The biggest difference
is that certain sparse configurations no longer have a fast-path.

The Torque pre-processing step replaces the existing Torque mechanism that
copied already pre-processed elements into the "work" FixedArray. The Torque
compacting works as follows:
  - Iterate all elements from 0 to {length}
    - If the element is the hole: Do nothing.
    - If the element is "undefined": Increment undefined counter.
    - In all other cases, push the element into the "work" FixedArray.

Then the "work" FixedArray is sorted as before. Writing the elements from
the "work" array back into the receiver, after sorting, has three steps:
  1. Copy the sorted elements from the "work" FixedArray to the receiver.
  2. Add previously counted number of "undefined" to the receiver.
  3. Depending on the backing store either delete properties or
     set them to the Hole up to {length}.

Bug: v8:8714
Change-Id: I14eccb7cfd2e4618bce2a85cba0689d7e0380ad2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1619756
Commit-Queue: Simon Zünd <szuend@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61812}
2019-05-24 06:18:45 +00:00

142 lines
3.6 KiB
JavaScript

// 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.
const kArraySize = 4000;
let template_array = [];
for (let i = 0; i < kArraySize; ++i) {
template_array[i] = Math.floor(Math.random() * kArraySize);
}
let array_to_sort = [];
function AssertPackedSmiElements() {
assert(%HasFastPackedElements(array_to_sort) &&
%HasSmiElements(array_to_sort),
"Element kind is not PACKED_SMI_ELEMENTS");
}
function AssertPackedDoubleElements() {
assert(%HasFastPackedElements(array_to_sort) &&
%HasDoubleElements(array_to_sort),
"Element kind is not PACKED_DOUBLE_ELEMENTS");
}
function AssertPackedObjectElements() {
assert(%HasFastPackedElements(array_to_sort) &&
%HasObjectElements(array_to_sort),
"Element kind is not PACKED_ELEMENTS");
}
function AssertHoleySmiElements() {
assert(%HasHoleyElements(array_to_sort) &&
%HasSmiElements(array_to_sort),
"Element kind is not HOLEY_SMI_ELEMENTS");
}
function AssertHoleyDoubleElements() {
assert(%HasHoleyElements(array_to_sort) &&
%HasDoubleElements(array_to_sort),
"Element kind is not HOLEY_DOUBLE_ELEMENTS");
}
function AssertHoleyObjectElements() {
assert(%HasHoleyElements(array_to_sort) &&
%HasObjectElements(array_to_sort),
"Element kind is not HOLEY_ELEMENTS");
}
function AssertDictionaryElements() {
assert(%HasDictionaryElements(array_to_sort),
"Element kind is not DICTIONARY_ELEMENTS");
}
function CreatePackedSmiArray() {
array_to_sort = Array.from(template_array);
AssertPackedSmiElements();
}
function CreatePackedDoubleArray() {
array_to_sort = Array.from(template_array, (x,_) => x + 0.1);
AssertPackedDoubleElements();
}
function CreatePackedObjectArray() {
array_to_sort = Array.from(template_array, (x,_) => `value ${x}`);
AssertPackedObjectElements();
}
function CreateHoleySmiArray() {
array_to_sort = Array.from(template_array);
delete array_to_sort[0];
AssertHoleySmiElements();
}
function CreateHoleyDoubleArray() {
array_to_sort = new Array(kArraySize);
for (let i = 0; i < kArraySize; ++i) {
array_to_sort[i] = template_array[i] + 0.1;
}
AssertHoleyDoubleElements();
}
function CreateHoleyObjectArray() {
array_to_sort = new Array(kArraySize);
for (let i = 0; i < kArraySize; ++i) {
array_to_sort[i] = `value ${template_array[i]}`;
}
AssertHoleyObjectElements();
}
function CreateDictionaryArray() {
array_to_sort = Array.from(template_array);
Object.defineProperty(array_to_sort, kArraySize - 2,
{ get: () => this.foo,
set: (v) => this.foo = v });
AssertDictionaryElements();
}
function Sort() {
array_to_sort.sort();
}
function CreateSortFn(comparefns = []) {
return () => {
for (let cmpfn of comparefns) {
array_to_sort.sort(cmpfn);
}
}
}
function cmp_smaller(a, b) {
if (a < b) return -1;
if (b < a) return 1;
return 0;
}
function cmp_greater(a, b) { return cmp_smaller(b, a); }
// The counter is used in some benchmarks to trigger actions during sorting.
// To keep benchmarks deterministic, the counter needs to be reset for each
// iteration.
let counter = 0;
// Sorting benchmarks need to execute setup and tearDown for each iteration.
// Otherwise the benchmarks would mainly measure sorting already sorted arrays
// which, depending on the strategy, is either the worst- or best case.
function createSortSuite(name, reference, run, setup, tearDown = () => {}) {
let run_fn = () => {
counter = 0;
setup();
run();
tearDown();
};
return createSuite(name, reference, run_fn);
}