Commit 67462272 authored by Caitlin Potter's avatar Caitlin Potter Committed by Commit Bot

[builtins] fix incorrect return value in ArrayIncludes

Take runtime path if startIndex parameter requires a ToInteger() call,
which can modify the elements kind of the receiver.

This removes a stub call from the builtin, and simplifies code slightly.

BUG=v8:5986
R=bmeurer@chromium.org, cbruni@chromium.org

Change-Id: Id238a81ab8ba28621858004b34d00a4356b8037f
Reviewed-on: https://chromium-review.googlesource.com/445006Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Cr-Commit-Position: refs/heads/master@{#43323}
parent 7a91e3c6
......@@ -1697,7 +1697,7 @@ void Builtins::Generate_ArrayIncludes(compiler::CodeAssemblerState* state) {
start_from_var(&assembler, MachineType::PointerRepresentation());
Label init_k(&assembler), return_true(&assembler), return_false(&assembler),
call_runtime(&assembler);
select_loop(&assembler), call_runtime(&assembler);
Label init_len(&assembler);
......@@ -1717,76 +1717,44 @@ void Builtins::Generate_ArrayIncludes(compiler::CodeAssemblerState* state) {
assembler.GotoIfNot(assembler.TaggedIsSmi(len), &call_runtime);
len_var.Bind(assembler.SmiToWord(len));
assembler.Branch(assembler.WordEqual(len_var.value(), intptr_zero),
&return_false, &init_k);
assembler.GotoIf(assembler.IsUndefined(start_from), &select_loop);
// Bailout to slow path if startIndex is not an Smi.
assembler.Branch(assembler.TaggedIsSmi(start_from), &init_k, &call_runtime);
}
assembler.Bind(&init_k);
{
Label done(&assembler), init_k_smi(&assembler), init_k_heap_num(&assembler),
Label init_k_smi(&assembler), init_k_heap_num(&assembler),
init_k_zero(&assembler), init_k_n(&assembler);
Node* tagged_n = assembler.ToInteger(context, start_from);
assembler.Branch(assembler.TaggedIsSmi(tagged_n), &init_k_smi,
&init_k_heap_num);
CSA_ASSERT(&assembler, assembler.TaggedIsSmi(start_from));
start_from_var.Bind(assembler.SmiUntag(start_from));
assembler.Bind(&init_k_smi);
{
start_from_var.Bind(assembler.SmiUntag(tagged_n));
assembler.Goto(&init_k_n);
}
Label if_positive(&assembler), if_negative(&assembler);
assembler.Branch(
assembler.IntPtrLessThan(start_from_var.value(), intptr_zero),
&if_negative, &if_positive);
assembler.Bind(&init_k_heap_num);
assembler.Bind(&if_positive);
{
Label do_return_false(&assembler);
// This round is lossless for all valid lengths.
Node* fp_len = assembler.RoundIntPtrToFloat64(len_var.value());
Node* fp_n = assembler.LoadHeapNumberValue(tagged_n);
assembler.GotoIf(assembler.Float64GreaterThanOrEqual(fp_n, fp_len),
&do_return_false);
start_from_var.Bind(assembler.ChangeInt32ToIntPtr(
assembler.TruncateFloat64ToWord32(fp_n)));
assembler.Goto(&init_k_n);
assembler.Bind(&do_return_false);
{
index_var.Bind(intptr_zero);
assembler.Goto(&return_false);
}
index_var.Bind(start_from_var.value());
assembler.Goto(&select_loop);
}
assembler.Bind(&init_k_n);
assembler.Bind(&if_negative);
{
Label if_positive(&assembler), if_negative(&assembler), done(&assembler);
assembler.Branch(
assembler.IntPtrLessThan(start_from_var.value(), intptr_zero),
&if_negative, &if_positive);
assembler.Bind(&if_positive);
{
index_var.Bind(start_from_var.value());
assembler.Goto(&done);
}
assembler.Bind(&if_negative);
{
index_var.Bind(
assembler.IntPtrAdd(len_var.value(), start_from_var.value()));
assembler.Branch(
assembler.IntPtrLessThan(index_var.value(), intptr_zero),
&init_k_zero, &done);
}
assembler.Bind(&init_k_zero);
{
index_var.Bind(intptr_zero);
assembler.Goto(&done);
}
assembler.Bind(&done);
Node* const index =
assembler.IntPtrAdd(len_var.value(), start_from_var.value());
index_var.Bind(assembler.SelectConstant(
assembler.IntPtrLessThan(index, intptr_zero), intptr_zero, index,
MachineType::PointerRepresentation()));
assembler.Goto(&select_loop);
}
}
assembler.Bind(&select_loop);
static int32_t kElementsKind[] = {
FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS,
......
// Copyright 2017 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: --allow-natives-syntax
var array = [1.7, 1.7, 1.7];
var mutator = {
[Symbol.toPrimitive]() {
Object.defineProperties(array, {
0: { get() { } },
1: { get() { } },
2: { get() { } },
});
return 0;
}
};
assertTrue(array.includes(undefined, mutator));
function search(array, searchElement, startIndex) {
return array.includes(searchElement, startIndex);
}
array = [1.7, 1.7, 1.7];
var not_mutator = { [Symbol.toPrimitive]() { return 0; } };
assertFalse(search(array, undefined, not_mutator));
assertFalse(search(array, undefined, not_mutator));
%OptimizeFunctionOnNextCall(search);
assertTrue(search(array, undefined, mutator));
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