[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/1174542 Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Commit-Queue: Hai Dang <dhai@google.com> Cr-Commit-Position: refs/heads/master@{#55149}
This commit is contained in:
parent
086d0c49d6
commit
3a606b91ef
@ -2573,13 +2573,10 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
|
||||
if (!NodeProperties::GetMapWitness(isolate(), node).ToHandle(&receiver_map))
|
||||
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 (!isolate()->IsNoElementsProtectorIntact()) return NoChange();
|
||||
if (IsHoleyElementsKind(receiver_map->elements_kind())) {
|
||||
dependencies()->DependOnProtector(
|
||||
PropertyCellRef(js_heap_broker(), factory()->no_elements_protector()));
|
||||
}
|
||||
|
@ -6,6 +6,22 @@
|
||||
|
||||
// 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 () {
|
||||
var array = [,];
|
||||
|
||||
@ -13,8 +29,8 @@
|
||||
return array.includes(val);
|
||||
}
|
||||
|
||||
assertEquals(includes(6), false);
|
||||
assertFalse(includes(6));
|
||||
|
||||
array.__proto__.push(6);
|
||||
assertEquals(includes(6), true);
|
||||
assertTrue(includes(6));
|
||||
})();
|
||||
|
@ -2,10 +2,26 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/* Test behaviors when the prototype has elements */
|
||||
|
||||
// indexOf
|
||||
|
||||
/* Test behaviors when the prototype has elements */
|
||||
|
||||
(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 () {
|
||||
var array = [,];
|
||||
|
||||
|
@ -8,6 +8,83 @@
|
||||
|
||||
// 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 () {
|
||||
var array = [,];
|
||||
|
||||
@ -18,9 +95,9 @@
|
||||
includes(6); includes(6);
|
||||
|
||||
%OptimizeFunctionOnNextCall(includes);
|
||||
assertEquals(includes(6), false);
|
||||
assertFalse(includes(6));
|
||||
|
||||
array.__proto__.push(6);
|
||||
// deopt
|
||||
assertEquals(includes(6), true);
|
||||
// deopt because of no_elements_protector
|
||||
assertTrue(includes(6));
|
||||
})();
|
||||
|
@ -8,6 +8,84 @@
|
||||
|
||||
// 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 () {
|
||||
var array = [,];
|
||||
|
||||
@ -21,6 +99,6 @@
|
||||
assertEquals(indexOf(6), -1);
|
||||
|
||||
array.__proto__.push(6);
|
||||
// deopt
|
||||
// deopt because of no_elements_protector
|
||||
assertEquals(indexOf(6), 0);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user