Fix bug with SIMD fast path of array.IndexOf/Includes and negative 0
For FixedDoubleArrays that are not aligned on 8 bytes, the SIMD fast path of array.IndexOf actually falls back on a scalar loop. Because of how this loop was written, it was failing to see that 0.0 == -0.0. Bug: chromium:1335445 Change-Id: Idf70fd3ed9950e5b2b7cc72bb2ebca6879b3a04e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3702803 Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Darius Mercadier <dmercadier@chromium.org> Cr-Commit-Position: refs/heads/main@{#81163}
This commit is contained in:
parent
747930df30
commit
00fe5f5e65
@ -354,8 +354,13 @@ Address ArrayIndexOfIncludes(Address array_start, uintptr_t array_len,
|
||||
if (reinterpret_cast<uintptr_t>(array) % sizeof(double) != 0) {
|
||||
// Slow scalar search for unaligned double array.
|
||||
for (; from_index < array_len; from_index++) {
|
||||
if (fixed_array.get_representation(static_cast<int>(from_index)) ==
|
||||
*reinterpret_cast<uint64_t*>(&search_num)) {
|
||||
if (fixed_array.is_the_hole(static_cast<int>(from_index))) {
|
||||
// |search_num| cannot be NaN, so there is no need to check against
|
||||
// holes.
|
||||
continue;
|
||||
}
|
||||
if (fixed_array.get_scalar(static_cast<int>(from_index)) ==
|
||||
search_num) {
|
||||
return from_index;
|
||||
}
|
||||
}
|
||||
|
37
test/mjsunit/regress/regress-crbug-1335445.js
Normal file
37
test/mjsunit/regress/regress-crbug-1335445.js
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
// This test checks that indexOf correctly sees that -0.0 == 0 when using its
|
||||
// SIMD fast path on unaligned FixedDoubleArrays. The issue with testing that is
|
||||
// that when creating an array from JavaScript, it's not possible to ensure that
|
||||
// it will be unaligned. Thus, we wrapped the test in a loop, which additionally
|
||||
// allocates some objects (or variable size), so that the array is eventually
|
||||
// not aligned. In practice, this looks fairly reliable: about half the arrays
|
||||
// are aligned on 8 bytes, and half are not.
|
||||
|
||||
// We store all the objects we create in this array, so that escape analysis
|
||||
// doesn't get rid of allocations.
|
||||
let objects = [];
|
||||
|
||||
for (let i = 0; i < 100; i++) {
|
||||
|
||||
for (let x = 0; x < i; x++) {
|
||||
if (i % 2 == 0) {
|
||||
objects.push({ i: 35 });
|
||||
} else {
|
||||
objects.push({ i: 35, "a":42 });
|
||||
}
|
||||
}
|
||||
|
||||
let arr = Array();
|
||||
objects.push(arr);
|
||||
for (let i = 0; i < 100; i++) {
|
||||
arr[i] = 1.5;
|
||||
}
|
||||
|
||||
arr[20] = -0.0;
|
||||
arr[23] = 0;
|
||||
|
||||
assertEquals(20, arr.indexOf(0));
|
||||
}
|
Loading…
Reference in New Issue
Block a user