v8/test/mjsunit/compiler/deopt-array-push.js
Ross McIlroy 2cb8a6e349 [Compile] Avoid flushing code that's marked for optimization in tests.
Bytecode flushing can make tests using assertOptimized flaky if the bytecode is
flushed between marking and optimization. It can also be flaky if the feedback vector
is collected before optimization. To prevent this, a new %PrepareForOptimization
runtime-test function is added that hold onto the bytecode strongly until it is
optimized after being explicitly marked for optimization by %OptimizeFunctionOnNextCall.

BUG=v8:8801,v8:8395

Change-Id: Idbd962a3a2044b915903f9c5e92d1789942b5b41
Reviewed-on: https://chromium-review.googlesource.com/c/1463525
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59914}
2019-02-27 16:44:24 +00:00

127 lines
3.0 KiB
JavaScript

// 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 --opt
(function test() {
function foo(a) { a.push(a.length = 2); }
%PrepareFunctionForOptimization(foo);
foo([1]);
foo([1]);
%OptimizeFunctionOnNextCall(foo);
foo([1]);
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
foo([1]);
assertOptimized(foo);
})();
(function testElementTypeCheckSmi() {
function foo(a) { a.push('a'); }
%PrepareFunctionForOptimization(foo);
foo([1]);
foo([1]);
%OptimizeFunctionOnNextCall(foo);
foo([1]);
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
foo([1]);
assertOptimized(foo);
})();
(function testElementTypeCheckDouble() {
function foo(a) { a.push('a'); }
%PrepareFunctionForOptimization(foo);
foo([0.3413312]);
foo([0.3413312]);
%OptimizeFunctionOnNextCall(foo);
foo([0.3413312]);
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
foo([0.3413312]);
assertOptimized(foo);
})();
(function test() {
function bar(a) { a.x = 2 };
%NeverOptimizeFunction(bar);
function foo(a) { a.push(bar(a)); }
%PrepareFunctionForOptimization(foo);
foo(["1"]);
foo(["1"]);
%OptimizeFunctionOnNextCall(foo);
foo(["1"]);
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
foo(["1"]);
assertOptimized(foo);
})();
(function test() {
function foo(a) { a.push(a.length = 2); }
%PrepareFunctionForOptimization(foo);
foo([0.34234]);
foo([0.34234]);
%OptimizeFunctionOnNextCall(foo);
foo([0.34234]);
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
foo([0.34234]);
assertOptimized(foo);
})();
(function test() {
const N = 128 * 1024;
function foo(a) { a.push(1); }
%PrepareFunctionForOptimization(foo);
foo(new Array(N));
foo(new Array(N));
%OptimizeFunctionOnNextCall(foo);
foo(new Array(N));
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
foo(new Array(N));
assertOptimized(foo);
})();
(function test() {
// Conservative arrays lengths in slow and fast mode.
const kFastModeLength = 1024;
const kSlowModeLength = 512 * 1024;
function mkArray(length) {
let a = [0.1];
a.length = length;
return a;
}
function foo(a) { a.push(0.23441233123); }
// 1. Optimize foo to handle fast mode arrays.
%PrepareFunctionForOptimization(foo);
foo(mkArray(kFastModeLength));
foo(mkArray(kFastModeLength));
%OptimizeFunctionOnNextCall(foo);
foo(mkArray(kFastModeLength));
assertOptimized(foo);
// Prepare foo to be re-optimized, ensuring it's bytecode / feedback vector
// doesn't get flushed after deoptimization.
%PrepareFunctionForOptimization(foo);
// 2. Given a slow mode array, foo will deopt.
foo(mkArray(kSlowModeLength));
// 3. Optimize foo again.
%OptimizeFunctionOnNextCall(foo);
foo(mkArray(kSlowModeLength));
// 4. It should stay optimized.
assertOptimized(foo);
})();