v8/test/mjsunit/compiler/number-divide.js
Mythri A aa4ee8d534 Add option to allocate feedback vector based on bytecode size
Currently, feedback vectors are allocated on a fixed budget of 1024.
In some cases it might be beneficial to allocate feedback vectors based
on invocation count rather than fixed budget. For example, if we have
a large function that is only run once. This cl adds an option to
use interrupt budget based on the bytecode size. It kind of mimics
invocation count. We would allocate feedback vectors early when we
have loops which is also required.

This flag is turned off by default. In followup cl, we will enable it
and if the memory / performance tradeoff is good we might make it
default.

Change-Id: I9f7231119b5fd65fb3268e665e2e315fb2625e1b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2584960
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Mythri Alle <mythria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72371}
2021-01-27 16:36:28 +00:00

224 lines
6.8 KiB
JavaScript

// Copyright 2018 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 --noalways-opt
// Test that NumberDivide with Number feedback works if only in the
// end SimplifiedLowering figures out that the inputs to this operation
// are actually Unsigned32.
(function() {
// We need a separately polluted % with NumberOrOddball feedback.
function bar(x) { return x / 2; }
%EnsureFeedbackVectorForFunction(bar);
bar(undefined); // The % feedback is now NumberOrOddball.
// Now just use the gadget above in a way that only after RETYPE
// in SimplifiedLowering we find out that the `x` is actually in
// Unsigned32 range (based on taking the SignedSmall feedback on
// the + operator).
function foo(x) {
x = (x >>> 0) + 1;
return bar(x) | 0;
}
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo(1));
assertEquals(1, foo(2));
assertEquals(2, foo(3));
assertEquals(2, foo(4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo(1));
assertEquals(1, foo(2));
assertEquals(2, foo(3));
assertEquals(2, foo(4));
assertOptimized(foo);
})();
// Test that NumberDivide with Number feedback works if only in the
// end SimplifiedLowering figures out that the inputs to this operation
// are actually Signed32.
(function() {
// We need a separately polluted % with NumberOrOddball feedback.
function bar(x) { return x / 2; }
%EnsureFeedbackVectorForFunction(bar);
bar(undefined); // The % feedback is now NumberOrOddball.
// Now just use the gadget above in a way that only after RETYPE
// in SimplifiedLowering we find out that the `x` is actually in
// Signed32 range (based on taking the SignedSmall feedback on
// the + operator).
function foo(x) {
x = (x | 0) + 1;
return bar(x) | 0;
}
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo(1));
assertEquals(1, foo(2));
assertEquals(2, foo(3));
assertEquals(2, foo(4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo(1));
assertEquals(1, foo(2));
assertEquals(2, foo(3));
assertEquals(2, foo(4));
assertOptimized(foo);
})();
// Test that SpeculativeNumberDivide turns into CheckedInt32Div, and
// that the "known power of two divisor" optimization works correctly.
(function() {
function foo(x) { return (x | 0) / 2; }
// Warmup with proper int32 divisions.
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo(2));
assertEquals(2, foo(4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo(6));
assertOptimized(foo);
// Make optimized code fail.
assertEquals(0.5, foo(1));
assertUnoptimized(foo);
// Try again with the new feedback, and now it should stay optimized.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals(4, foo(8));
assertOptimized(foo);
assertEquals(0.5, foo(1));
assertOptimized(foo);
})();
// Test that SpeculativeNumberDivide turns into CheckedInt32Div, and
// that the optimized code properly bails out on "division by zero".
(function() {
function foo(x, y) { return x / y; }
// Warmup with proper int32 divisions.
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo(4, 2));
assertEquals(2, foo(8, 4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo(2, 2));
assertOptimized(foo);
// Make optimized code fail.
assertEquals(Infinity, foo(1, 0));
assertUnoptimized(foo);
// Try again with the new feedback, and now it should stay optimized.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo(2, 1));
assertOptimized(foo);
assertEquals(Infinity, foo(1, 0));
assertOptimized(foo);
})();
// Test that SpeculativeNumberDivide turns into CheckedInt32Div, and
// that the optimized code properly bails out on minus zero.
(function() {
function foo(x, y) { return x / y; }
// Warmup with proper int32 divisions.
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo(4, 2));
assertEquals(2, foo(8, 4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo(2, 2));
assertOptimized(foo);
// Make optimized code fail.
assertEquals(-0, foo(0, -1));
assertUnoptimized(foo);
// Try again with the new feedback, and now it should stay optimized.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo(2, 1));
assertOptimized(foo);
assertEquals(-0, foo(0, -1));
assertOptimized(foo);
})();
// Test that SpeculativeNumberDivide turns into CheckedInt32Div, and
// that the optimized code properly bails out if result is -kMinInt.
(function() {
function foo(x, y) { return x / y; }
// Warmup with proper int32 divisions.
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo(4, 2));
assertEquals(2, foo(8, 4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo(2, 2));
assertOptimized(foo);
// Make optimized code fail.
assertEquals(2147483648, foo(-2147483648, -1));
assertUnoptimized(foo);
// Try again with the new feedback, and now it should stay optimized.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo(2, 1));
assertOptimized(foo);
assertEquals(2147483648, foo(-2147483648, -1));
assertOptimized(foo);
})();
// Test that SpeculativeNumberDivide turns into CheckedUint32Div, and
// that the "known power of two divisor" optimization works correctly.
(function() {
function foo(s) { return s.length / 2; }
// Warmup with proper uint32 divisions.
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo("ab".repeat(1)));
assertEquals(2, foo("ab".repeat(2)));
%OptimizeFunctionOnNextCall(foo);
assertEquals(3, foo("ab".repeat(3)));
assertOptimized(foo);
// Make optimized code fail.
assertEquals(0.5, foo("a"));
assertUnoptimized(foo);
// Try again with the new feedback, and now it should stay optimized.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals(4, foo("ab".repeat(4)));
assertOptimized(foo);
assertEquals(0.5, foo("a"));
assertOptimized(foo);
})();
// Test that SpeculativeNumberDivide turns into CheckedUint32Div, and
// that the optimized code properly bails out on "division by zero".
(function() {
function foo(x, y) { return (x >>> 0) / (y >>> 0); }
// Warmup with proper uint32 divisions.
%PrepareFunctionForOptimization(foo);
assertEquals(2, foo(4, 2));
assertEquals(2, foo(8, 4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(1, foo(2, 2));
assertOptimized(foo);
// Make optimized code fail.
assertEquals(Infinity, foo(1, 0));
assertUnoptimized(foo);
// Try again with the new feedback, and now it should stay optimized.
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals(2, foo(2, 1));
assertOptimized(foo);
assertEquals(Infinity, foo(1, 0));
assertOptimized(foo);
})();