Commit b4470ea4 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

Reland "[bigint] Fix early-return in asIntN"

For "top digit" (of the result) comparison to be applicable, we must
also check that there are no further digits in the source.

The included regression test flushes out another bug in "TruncateToNBits",
so that gets fixed here too (in contrast to the first landing attempt).

This reverts commit cb9e7af4.

Bug: v8:7150
Change-Id: Id631b1ae79e60b8e85ed4667e246a64c46765f2b
Reviewed-on: https://chromium-review.googlesource.com/807348Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49877}
parent 4d95c4b0
......@@ -1928,12 +1928,13 @@ Handle<BigInt> BigInt::AsIntN(uint64_t n, Handle<BigInt> x) {
if (x->is_zero()) return x;
if (n == 0) return MutableBigInt::Zero(x->GetIsolate());
uint64_t needed_length = (n + kDigitBits - 1) / kDigitBits;
uint64_t x_length = static_cast<uint64_t>(x->length());
// If {x} has less than {n} bits, return it directly.
if (static_cast<uint64_t>(x->length()) < needed_length) return x;
if (x_length < needed_length) return x;
DCHECK_LE(needed_length, kMaxInt);
digit_t top_digit = x->digit(static_cast<int>(needed_length) - 1);
digit_t compare_digit = static_cast<digit_t>(1) << ((n - 1) % kDigitBits);
if (top_digit < compare_digit) return x;
if (x_length == needed_length && top_digit < compare_digit) return x;
// Otherwise we have to truncate (which is a no-op in the special case
// of x == -2^(n-1)), and determine the right sign. We also might have
// to subtract from 2^n to simulate having two's complement representation.
......@@ -2010,8 +2011,11 @@ Handle<BigInt> MutableBigInt::TruncateToNBits(int n, Handle<BigInt> x) {
// The MSD might contain extra bits that we don't want.
digit_t msd = x->digit(last);
int drop = kDigitBits - (n % kDigitBits);
result->set_digit(last, (msd << drop) >> drop);
if (n % kDigitBits != 0) {
int drop = kDigitBits - (n % kDigitBits);
msd = (msd << drop) >> drop;
}
result->set_digit(last, msd);
result->set_sign(x->sign());
return MakeImmutable(result);
}
......
......@@ -145,6 +145,8 @@
}{
assertThrows(() => BigInt.asIntN(3, 12), TypeError);
assertEquals(-4n, BigInt.asIntN(3, "12"));
assertEquals(0x123456789abcdefn,
BigInt.asIntN(64, 0xabcdef0123456789abcdefn));
}
// BigInt.asUintN
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment