v8/test/mjsunit/es6/array-iterator-turbo.js
caitp 7f21e67b38 [builtins] implement JSBuiltinReducer for ArrayIteratorNext()
Adds a protector cell to prevent inlining (which will likely lead to deopt
loops) when a JSArrayIterator's array transitions from a fast JSArray to a
slow JSArray (such as, when the array is touched during iteration in a way
which triggers a map transition).

Also adds TODO comments relating to the spec update proposed by Dan at
https://github.com/tc39/ecma262/pull/724

BUG=v8:5388
R=bmeurer@chromium.org, mstarzinger@chromium.org
TBR=hpayer@chromium.org, ulan@chromium.org

Review-Url: https://codereview.chromium.org/2484003002
Cr-Commit-Position: refs/heads/master@{#40970}
2016-11-14 15:59:47 +00:00

244 lines
6.5 KiB
JavaScript

// Copyright 2016 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: --turbo --turbo-escape --allow-natives-syntax
"use strict";
const kDeoptimized = 2;
const kTurbofanned = 7;
const kInterpreted = 8;
function GetOptimizationStatus(fn) {
let status = %GetOptimizationStatus(fn);
switch (status) {
case kInterpreted: // Treat interpreted frames as unoptimized
status = kDeoptimized;
break;
}
return status;
}
let global = this;
let tests = {
FastElementsKind() {
let runners = {
FAST_SMI_ELEMENTS(array) {
let sum = 0;
for (let x of array) sum += x;
return sum;
},
FAST_HOLEY_SMI_ELEMENTS(array) {
let sum = 0;
for (let x of array) {
if (x) sum += x;
}
return sum;
},
FAST_ELEMENTS(array) {
let ret = "";
for (let str of array) ret += `> ${str}`;
return ret;
},
FAST_HOLEY_ELEMENTS(array) {
let ret = "";
for (let str of array) ret += `> ${str}`;
return ret;
},
FAST_DOUBLE_ELEMENTS(array) {
let sum = 0.0;
for (let x of array) sum += x;
return sum;
},
FAST_HOLEY_DOUBLE_ELEMENTS(array) {
let sum = 0.0;
for (let x of array) {
if (x) sum += x;
}
return sum;
}
};
let tests = {
FAST_SMI_ELEMENTS: {
array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
expected: 55,
array2: [1, 2, 3],
expected2: 6
},
FAST_HOLEY_SMI_ELEMENTS: {
array: [1, , 3, , 5, , 7, , 9, ,],
expected: 25,
array2: [1, , 3],
expected2: 4
},
FAST_ELEMENTS: {
array: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
expected: "> a> b> c> d> e> f> g> h> i> j",
array2: ["a", "b", "c"],
expected2: "> a> b> c"
},
FAST_HOLEY_ELEMENTS: {
array: ["a", , "c", , "e", , "g", , "i", ,],
expected: "> a> undefined> c> undefined> e> undefined> g" +
"> undefined> i> undefined",
array2: ["a", , "c"],
expected2: "> a> undefined> c"
},
FAST_DOUBLE_ELEMENTS: {
array: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
expected: 5.5,
array2: [0.6, 0.4, 0.2],
expected2: 1.2
},
FAST_HOLEY_DOUBLE_ELEMENTS: {
array: [0.1, , 0.3, , 0.5, , 0.7, , 0.9, ,],
expected: 2.5,
array2: [0.1, , 0.3],
expected2: 0.4
}
};
for (let key of Object.keys(runners)) {
let fn = runners[key];
let { array, expected, array2, expected2 } = tests[key];
// Warmup:
fn(array);
fn(array);
%OptimizeFunctionOnNextCall(fn);
fn(array);
// TODO(bmeurer): FAST_HOLEY_DOUBLE_ELEMENTS maps generally deopt when
// a hole is encountered. Test should be fixed once that is corrected.
let status = /HOLEY_DOUBLE/.test(key) ? kDeoptimized : kTurbofanned;
assertEquals(status, GetOptimizationStatus(fn), key);
assertEquals(expected, fn(array), key);
assertEquals(status, GetOptimizationStatus(fn), key);
// Check no deopt when another arra with the same map is used
assertTrue(%HaveSameMap(array, array2), key);
assertEquals(status, GetOptimizationStatus(fn), key);
assertEquals(expected2, fn(array2), key);
// CheckMaps bailout
let newArray = Object.defineProperty(
[1, 2, 3], 2, { enumerable: false, configurable: false,
get() { return 7; } });
fn(newArray);
assertEquals(kDeoptimized, GetOptimizationStatus(fn), key);
}
},
TypedArrays() {
let tests = {
Uint8Array: {
array: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, -1, 256]),
expected: 291,
array2: new Uint8Array([1, 2, 3]),
expected2: 6
},
Int8Array: {
array: new Int8Array([1, 2, 3, 4, 5, 6, 7, 8, -129, 128]),
expected: 35,
array2: new Int8Array([1, 2, 3]),
expected2: 6
},
Uint16Array: {
array: new Uint16Array([1, 2, 3, 4, 5, 6, 7, 8, -1, 0x10000]),
expected: 65571,
array2: new Uint16Array([1, 2, 3]),
expected2: 6
},
Int16Array: {
array: new Int16Array([1, 2, 3, 4, 5, 6, 7, 8, -32769, 0x7FFF]),
expected: 65570,
array2: new Int16Array([1, 2, 3]),
expected2: 6
},
Uint32Array: {
array: new Uint32Array([1, 2, 3, 4, 5, 6, 7, 8, -1, 0x100000000]),
expected: 4294967331,
array2: new Uint32Array([1, 2, 3]),
expected2: 6
},
Int32Array: {
array: new Int32Array([1, 2, 3, 4, 5, 6, 7, 8,
-2147483649, 0x7FFFFFFF]),
expected: 4294967330,
array2: new Int32Array([1, 2, 3]),
expected2: 6
},
Float32Array: {
array: new Float32Array([9.5, 8.0, 7.0, 7.0, 5.0, 4.0, 3.0, 2.0]),
expected: 45.5,
array2: new Float32Array([10.5, 5.5, 1.5]),
expected2: 17.5
},
Float64Array: {
array: new Float64Array([9.5, 8.0, 7.0, 7.0, 5.0, 4.0, 3.0, 2.0]),
expected: 45.5,
array2: new Float64Array([10.5, 5.5, 1.5]),
expected2: 17.5
},
Uint8ClampedArray: {
array: new Uint8ClampedArray([4.3, 7.45632, 3.14, 4.61, 5.0004, 6.493,
7.12, 8, 1.7, 3.6]),
expected: 51,
array2: new Uint8ClampedArray([1, 2, 3]),
expected2: 6
}
};
for (let key of Object.keys(tests)) {
let test = tests[key];
let { array, expected, array2, expected2 } = test;
let sum = function(array) {
let ret = 0;
for (let x of array) ret += x;
return ret;
};
// Warmup
sum(array);
sum(array);
%OptimizeFunctionOnNextCall(sum);
assertEquals(expected, sum(array), key);
assertEquals(kTurbofanned, GetOptimizationStatus(sum), key);
// Not deoptimized when called on typed array of same type / map
assertTrue(%HaveSameMap(array, array2));
assertEquals(expected2, sum(array2), key);
assertEquals(kTurbofanned, GetOptimizationStatus(sum), key);
// Throw when detached
let clone = new array.constructor(array);
%ArrayBufferNeuter(clone.buffer);
assertThrows(() => sum(clone), TypeError);
}
}
};
for (let name of Object.keys(tests)) {
let test = tests[name];
test();
}