Commit 3a606b91 authored by Hai Dang's avatar Hai Dang Committed by Commit Bot

[turbofan] Add additional checks for the JSCallReducer of Array#indexOf/includes.

This fixes the bug where the reducer ignores a prototype that is not
initial. Tests are also added.

Bug: v8:8056
Change-Id: I428eed2d2790fffa22f67a051f7d1f1e4d3ce947
Reviewed-on: https://chromium-review.googlesource.com/1174542Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Hai Dang <dhai@google.com>
Cr-Commit-Position: refs/heads/master@{#55149}
parent 086d0c49
...@@ -2573,13 +2573,10 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes( ...@@ -2573,13 +2573,10 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
if (!NodeProperties::GetMapWitness(isolate(), node).ToHandle(&receiver_map)) if (!NodeProperties::GetMapWitness(isolate(), node).ToHandle(&receiver_map))
return NoChange(); return NoChange();
if (receiver_map->instance_type() != JS_ARRAY_TYPE) return NoChange(); if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
return NoChange();
const ElementsKind kind = receiver_map->elements_kind();
if (!IsFastElementsKind(kind)) return NoChange();
if (IsHoleyElementsKind(kind)) { if (IsHoleyElementsKind(receiver_map->elements_kind())) {
if (!isolate()->IsNoElementsProtectorIntact()) return NoChange();
dependencies()->DependOnProtector( dependencies()->DependOnProtector(
PropertyCellRef(js_heap_broker(), factory()->no_elements_protector())); PropertyCellRef(js_heap_broker(), factory()->no_elements_protector()));
} }
......
...@@ -6,6 +6,22 @@ ...@@ -6,6 +6,22 @@
// includes // includes
(function() {
const iarr = [,3];
function includes(arr, val) {
return arr.includes(val);
}
assertFalse(includes(iarr, 2));
assertTrue(includes(iarr, 3));
iarr.__proto__ = [2];
assertTrue(includes(iarr, 2));
})();
// This pollutes the Array prototype, so we should not run more tests
// in the same environment after this.
(function () { (function () {
var array = [,]; var array = [,];
...@@ -13,8 +29,8 @@ ...@@ -13,8 +29,8 @@
return array.includes(val); return array.includes(val);
} }
assertEquals(includes(6), false); assertFalse(includes(6));
array.__proto__.push(6); array.__proto__.push(6);
assertEquals(includes(6), true); assertTrue(includes(6));
})(); })();
...@@ -2,10 +2,26 @@ ...@@ -2,10 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// indexOf
/* Test behaviors when the prototype has elements */ /* Test behaviors when the prototype has elements */
// indexOf (function() {
const iarr = [,3];
function indexOf(arr, val) {
return arr.indexOf(val);
}
assertEquals(-1, indexOf(iarr, 2));
assertEquals(1, indexOf(iarr, 3));
iarr.__proto__ = [2];
assertEquals(0, indexOf(iarr, 2));
})();
// This pollutes the Array prototype, so we should not run more tests
// in the same environment after this.
(function () { (function () {
var array = [,]; var array = [,];
......
...@@ -8,6 +8,83 @@ ...@@ -8,6 +8,83 @@
// includes // includes
(function() {
const iarr = [0,1,2];
const darr = [0.0, 2.0, 3.3];
function includes(arr, val) {
return arr.includes(val);
}
assertTrue(includes(iarr, 0)); assertTrue(includes(darr, 0));
assertTrue(includes(iarr, 2)); assertTrue(includes(darr, 2));
// JSCallReducer for includes not reduce because it only works with single map
%OptimizeFunctionOnNextCall(includes);
assertTrue(includes(iarr, 0));
assertTrue(includes(darr, 0));
})();
(function() {
const iarr = [0,1,2];
function includes(arr, val) {
return arr.includes(val);
}
assertTrue(includes(iarr, 0));
assertTrue(includes(iarr, 2));
%OptimizeFunctionOnNextCall(includes);
assertTrue(includes(iarr, 0));
const darr = [0.0, 2.0, 3.3];
// deopt because of map change
assertTrue(includes(darr, 0));
})();
(function() {
const iarr = [,3];
function includes(arr, val) {
return arr.includes(val);
}
iarr.__proto__ = [2];
// get feedback
assertFalse(includes(iarr, 0));
assertTrue(includes(iarr, 2));
%OptimizeFunctionOnNextCall(includes);
assertFalse(includes(iarr, 0));
assertTrue(includes(iarr, 2));
})();
(function() {
const iarr = [,3];
function includes(arr, val) {
return arr.includes(val);
}
assertFalse(includes(iarr, 2));
assertTrue(includes(iarr, 3));
%OptimizeFunctionOnNextCall(includes);
assertFalse(includes(iarr, 2));
// deopt because of map change
iarr.__proto__ = [2];
assertTrue(includes(iarr, 2));
})();
// This pollutes the Array prototype, so we should not run more tests
// in the same environment after this.
(function () { (function () {
var array = [,]; var array = [,];
...@@ -18,9 +95,9 @@ ...@@ -18,9 +95,9 @@
includes(6); includes(6); includes(6); includes(6);
%OptimizeFunctionOnNextCall(includes); %OptimizeFunctionOnNextCall(includes);
assertEquals(includes(6), false); assertFalse(includes(6));
array.__proto__.push(6); array.__proto__.push(6);
// deopt // deopt because of no_elements_protector
assertEquals(includes(6), true); assertTrue(includes(6));
})(); })();
...@@ -8,6 +8,84 @@ ...@@ -8,6 +8,84 @@
// indexOf // indexOf
(function() {
const iarr = [0,1,2];
const darr = [0.0, 2.0, 3.3];
function indexOf(arr, val) {
return arr.indexOf(val);
}
assertEquals(0, indexOf(iarr, 0));
assertEquals(0, indexOf(darr, 0));
assertEquals(2, indexOf(iarr, 2));
assertEquals(1, indexOf(darr, 2));
// JSCallReducer for indexOf will not reduce
// because it only works with single map
%OptimizeFunctionOnNextCall(indexOf);
assertEquals(0, indexOf(iarr, 0));
assertEquals(0, indexOf(darr, 0));
})();
(function() {
const iarr = [0,1,2];
function indexOf(arr, val) {
return arr.indexOf(val);
}
assertEquals(0, indexOf(iarr, 0));
assertEquals(2, indexOf(iarr, 2));
%OptimizeFunctionOnNextCall(indexOf);
assertEquals(0, indexOf(iarr, 0));
const darr = [0.0, 2.0, 3.3];
// deopt because of map change
assertEquals(0, indexOf(darr, 0));
})();
(function() {
const iarr = [,3];
function indexOf(arr, val) {
return arr.indexOf(val);
}
iarr.__proto__ = [2];
assertEquals(-1, indexOf(iarr, 0));
assertEquals(0, indexOf(iarr, 2));
%OptimizeFunctionOnNextCall(indexOf);
assertEquals(-1, indexOf(iarr, 0));
assertEquals(0, indexOf(iarr, 2));
})();
(function() {
const iarr = [,3];
function indexOf(arr, val) {
return arr.indexOf(val);
}
assertEquals(-1, indexOf(iarr, 2));
assertEquals(1, indexOf(iarr, 3));
%OptimizeFunctionOnNextCall(indexOf);
assertEquals(-1, indexOf(iarr, 2));
// deopt because of map change
iarr.__proto__ = [2];
assertEquals(0, indexOf(iarr, 2));
})();
// This pollutes the Array prototype, so we should not run more tests
// in the same environment after this.
(function () { (function () {
var array = [,]; var array = [,];
...@@ -21,6 +99,6 @@ ...@@ -21,6 +99,6 @@
assertEquals(indexOf(6), -1); assertEquals(indexOf(6), -1);
array.__proto__.push(6); array.__proto__.push(6);
// deopt // deopt because of no_elements_protector
assertEquals(indexOf(6), 0); assertEquals(indexOf(6), 0);
})(); })();
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