2690e2e3a3
This CL implements Torque builtins for BigInt left shift and right shift and truncates shift operations when the shift amount is a constant. - Propagate truncation if we know the operation is a left shift. - Lower the operation to a word64 right shift if the lhs is Signed- or UnsignedBigInt64 and we know the op is a right shift. A side effect of truncating left shift is it will not throw a BigIntTooBig exception in optimized code. Bug: v8:9407 Change-Id: Ibd42cf897ef8a35f6addd09674faf409654d6d7c Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4028142 Commit-Queue: Qifan Pan <panq@google.com> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/main@{#84396}
111 lines
3.7 KiB
JavaScript
111 lines
3.7 KiB
JavaScript
// Copyright 2022 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 --turbofan --no-always-turbofan
|
|
|
|
(function OptimizeAndTest() {
|
|
function ShiftLeft(a, b) {
|
|
return a << b;
|
|
}
|
|
%PrepareFunctionForOptimization(ShiftLeft);
|
|
assertEquals(0n, ShiftLeft(0n, 42n));
|
|
assertEquals(-42n, ShiftLeft(-42n, 0n));
|
|
assertEquals(2n ** 42n, ShiftLeft(1n, 42n));
|
|
assertEquals(-2n, ShiftLeft(-(2n ** 512n), -511n));
|
|
assertEquals(-1n, ShiftLeft(-(2n ** 512n), -513n));
|
|
|
|
%OptimizeFunctionOnNextCall(ShiftLeft);
|
|
assertEquals(0n, ShiftLeft(0n, 42n));
|
|
assertEquals(-42n, ShiftLeft(-42n, 0n));
|
|
assertEquals(2n ** 42n, ShiftLeft(1n, 42n));
|
|
assertEquals(-2n, ShiftLeft(-(2n ** 512n), -511n));
|
|
assertEquals(-1n, ShiftLeft(-(2n ** 512n), -513n));
|
|
assertOptimized(ShiftLeft);
|
|
|
|
assertThrows(() => ShiftLeft(1n, 2n ** 30n), RangeError);
|
|
assertUnoptimized(ShiftLeft);
|
|
})();
|
|
|
|
(function OptimizeAndTest() {
|
|
function ShiftLeftByPositive(a) {
|
|
return BigInt.asIntN(62, a << 42n);
|
|
}
|
|
%PrepareFunctionForOptimization(ShiftLeftByPositive);
|
|
assertEquals(0n, ShiftLeftByPositive(0n));
|
|
|
|
%OptimizeFunctionOnNextCall(ShiftLeftByPositive);
|
|
assertEquals(0n, ShiftLeftByPositive(0n));
|
|
assertEquals(2n ** 42n, ShiftLeftByPositive(1n));
|
|
assertEquals(2n ** 42n, ShiftLeftByPositive(1n + 2n ** 62n));
|
|
assertEquals(-(2n ** 42n), ShiftLeftByPositive(-1n - 2n ** 64n));
|
|
assertOptimized(ShiftLeftByPositive);
|
|
|
|
assertThrows(() => ShiftLeftByPositive(0), TypeError);
|
|
assertUnoptimized(ShiftLeftByPositive);
|
|
})();
|
|
|
|
(function OptimizeAndTest() {
|
|
const minus42 = -42n;
|
|
function ShiftLeftByNegative(a) {
|
|
return BigInt.asIntN(62, BigInt.asUintN(64, a) << minus42);
|
|
}
|
|
%PrepareFunctionForOptimization(ShiftLeftByNegative);
|
|
assertEquals(0n, ShiftLeftByNegative(0n));
|
|
|
|
%OptimizeFunctionOnNextCall(ShiftLeftByNegative);
|
|
assertEquals(0n, ShiftLeftByNegative(42n));
|
|
assertEquals(4194303n, ShiftLeftByNegative(-42n));
|
|
assertEquals(2n ** 20n, ShiftLeftByNegative(1n + 2n ** 62n));
|
|
assertEquals(3145727n, ShiftLeftByNegative(-1n - 2n ** 62n - 2n ** 64n));
|
|
assertOptimized(ShiftLeftByNegative);
|
|
|
|
assertThrows(() => ShiftLeftByNegative(0), TypeError);
|
|
if (%Is64Bit()) {
|
|
// BigInt truncation is not inlined on 32-bit platforms so there is no
|
|
// checks for BigInt, thus deopt will not be triggered.
|
|
assertUnoptimized(ShiftLeftByNegative);
|
|
}
|
|
})();
|
|
|
|
(function OptimizeAndTest() {
|
|
function ShiftLeftBy64(a) {
|
|
return BigInt.asIntN(62, a << 64n);
|
|
}
|
|
%PrepareFunctionForOptimization(ShiftLeftBy64);
|
|
assertEquals(0n, ShiftLeftBy64(0n));
|
|
|
|
%OptimizeFunctionOnNextCall(ShiftLeftBy64);
|
|
assertEquals(0n, ShiftLeftBy64(0n));
|
|
assertEquals(0n, ShiftLeftBy64(1n));
|
|
assertEquals(0n, ShiftLeftBy64(1n + 2n ** 62n));
|
|
assertEquals(0n, ShiftLeftBy64(-1n - 2n ** 64n));
|
|
assertOptimized(ShiftLeftBy64);
|
|
|
|
assertThrows(() => ShiftLeftBy64(0), TypeError);
|
|
assertUnoptimized(ShiftLeftBy64);
|
|
})();
|
|
|
|
(function OptimizeAndTest() {
|
|
const bi = 2n ** 64n;
|
|
function ShiftLeftByLarge(a) {
|
|
return BigInt.asIntN(62, a << bi);
|
|
}
|
|
%PrepareFunctionForOptimization(ShiftLeftByLarge);
|
|
assertEquals(0n, ShiftLeftByLarge(0n));
|
|
|
|
%OptimizeFunctionOnNextCall(ShiftLeftByLarge);
|
|
assertEquals(0n, ShiftLeftByLarge(0n));
|
|
if (%Is64Bit()) {
|
|
// After optimization, a truncated left shift will not throw a
|
|
// BigIntTooBig exception just as truncated addition.
|
|
assertEquals(0n, ShiftLeftByLarge(1n));
|
|
assertEquals(0n, ShiftLeftByLarge(1n + 2n ** 62n));
|
|
assertEquals(0n, ShiftLeftByLarge(-1n - 2n ** 64n));
|
|
}
|
|
assertOptimized(ShiftLeftByLarge);
|
|
|
|
assertThrows(() => ShiftLeftByLarge(0), TypeError);
|
|
assertUnoptimized(ShiftLeftByLarge);
|
|
})();
|