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

[bigint] Implement shift ops

Bug: v8:6791
Change-Id: I5e91832bcb74e895eaf7a3d6ee493c832abba7bf
Reviewed-on: https://chromium-review.googlesource.com/699635
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48299}
parent c5625884
...@@ -275,6 +275,7 @@ class ErrorUtils : public AllStatic { ...@@ -275,6 +275,7 @@ class ErrorUtils : public AllStatic {
"The comparison function must be either a function or undefined") \ "The comparison function must be either a function or undefined") \
T(BigIntMixedTypes, \ T(BigIntMixedTypes, \
"Cannot mix BigInt and other types, use explicit conversions") \ "Cannot mix BigInt and other types, use explicit conversions") \
T(BigIntShr, "BigInts have no unsigned right shift, use >> instead") \
T(CalledNonCallable, "% is not a function") \ T(CalledNonCallable, "% is not a function") \
T(CalledOnNonObject, "% called on non-object") \ T(CalledOnNonObject, "% called on non-object") \
T(CalledOnNullOrUndefined, "% called on null or undefined") \ T(CalledOnNullOrUndefined, "% called on null or undefined") \
......
...@@ -136,17 +136,23 @@ Handle<BigInt> BigInt::Subtract(Handle<BigInt> x, Handle<BigInt> y) { ...@@ -136,17 +136,23 @@ Handle<BigInt> BigInt::Subtract(Handle<BigInt> x, Handle<BigInt> y) {
return AbsoluteSub(y, x, !xsign); return AbsoluteSub(y, x, !xsign);
} }
Handle<BigInt> BigInt::LeftShift(Handle<BigInt> x, Handle<BigInt> y) { MaybeHandle<BigInt> BigInt::LeftShift(Handle<BigInt> x, Handle<BigInt> y) {
UNIMPLEMENTED(); // TODO(jkummerow): Implement. if (y->is_zero() || x->is_zero()) return x;
if (y->sign()) return RightShiftByAbsolute(x, y);
return LeftShiftByAbsolute(x, y);
} }
Handle<BigInt> BigInt::SignedRightShift(Handle<BigInt> x, Handle<BigInt> y) { MaybeHandle<BigInt> BigInt::SignedRightShift(Handle<BigInt> x,
UNIMPLEMENTED(); // TODO(jkummerow): Implement. Handle<BigInt> y) {
if (y->is_zero() || x->is_zero()) return x;
if (y->sign()) return LeftShiftByAbsolute(x, y);
return RightShiftByAbsolute(x, y);
} }
MaybeHandle<BigInt> BigInt::UnsignedRightShift(Handle<BigInt> x, MaybeHandle<BigInt> BigInt::UnsignedRightShift(Handle<BigInt> x,
Handle<BigInt> y) { Handle<BigInt> y) {
UNIMPLEMENTED(); // TODO(jkummerow): Implement. THROW_NEW_ERROR(x->GetIsolate(), NewTypeError(MessageTemplate::kBigIntShr),
BigInt);
} }
bool BigInt::LessThan(Handle<BigInt> x, Handle<BigInt> y) { bool BigInt::LessThan(Handle<BigInt> x, Handle<BigInt> y) {
...@@ -770,6 +776,144 @@ Handle<BigInt> BigInt::SpecialLeftShift(Handle<BigInt> x, int shift, ...@@ -770,6 +776,144 @@ Handle<BigInt> BigInt::SpecialLeftShift(Handle<BigInt> x, int shift,
return result; return result;
} }
MaybeHandle<BigInt> BigInt::LeftShiftByAbsolute(Handle<BigInt> x,
Handle<BigInt> y) {
Isolate* isolate = x->GetIsolate();
Maybe<digit_t> maybe_shift = ToShiftAmount(y);
if (maybe_shift.IsNothing()) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig),
BigInt);
}
digit_t shift = maybe_shift.FromJust();
int digit_shift = static_cast<int>(shift / kDigitBits);
int bits_shift = static_cast<int>(shift % kDigitBits);
int length = x->length();
bool grow = bits_shift != 0 &&
(x->digit(length - 1) >> (kDigitBits - bits_shift)) != 0;
int result_length = length + digit_shift + grow;
if (result_length > kMaxLength) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig),
BigInt);
}
Handle<BigInt> result = isolate->factory()->NewBigIntRaw(result_length);
if (bits_shift == 0) {
int i = 0;
for (; i < digit_shift; i++) result->set_digit(i, 0ul);
for (; i < result_length; i++) {
result->set_digit(i, x->digit(i - digit_shift));
}
} else {
digit_t carry = 0;
for (int i = 0; i < digit_shift; i++) result->set_digit(i, 0ul);
for (int i = 0; i < length; i++) {
digit_t d = x->digit(i);
result->set_digit(i + digit_shift, (d << bits_shift) | carry);
carry = d >> (kDigitBits - bits_shift);
}
if (grow) {
result->set_digit(length + digit_shift, carry);
} else {
DCHECK(carry == 0);
}
}
result->set_sign(x->sign());
result->RightTrim();
return result;
}
Handle<BigInt> BigInt::RightShiftByAbsolute(Handle<BigInt> x,
Handle<BigInt> y) {
Isolate* isolate = x->GetIsolate();
int length = x->length();
bool sign = x->sign();
Maybe<digit_t> maybe_shift = ToShiftAmount(y);
if (maybe_shift.IsNothing()) {
return RightShiftByMaximum(isolate, sign);
}
digit_t shift = maybe_shift.FromJust();
int digit_shift = static_cast<int>(shift / kDigitBits);
int bits_shift = static_cast<int>(shift % kDigitBits);
int result_length = length - digit_shift;
if (result_length <= 0) {
return RightShiftByMaximum(isolate, sign);
}
// For negative numbers, round down if any bit was shifted out (so that e.g.
// -5n >> 1n == -3n and not -2n). Check now whether this will happen and
// whether it can cause overflow into a new digit. If we allocate the result
// large enough up front, it avoids having to do a second allocation later.
bool must_round_down = false;
if (sign) {
if ((x->digit(digit_shift) & ((1 << bits_shift) - 1)) != 0) {
must_round_down = true;
} else {
for (int i = 0; i < digit_shift; i++) {
if (x->digit(i) != 0) {
must_round_down = true;
break;
}
}
}
}
// If bits_shift is non-zero, it frees up bits, preventing overflow.
if (must_round_down && bits_shift == 0) {
// Overflow cannot happen if the most significant digit has unset bits.
digit_t msd = x->digit(length - 1);
bool rounding_can_overflow = digit_ismax(msd);
if (rounding_can_overflow) result_length++;
}
Handle<BigInt> result = isolate->factory()->NewBigIntRaw(result_length);
if (bits_shift == 0) {
for (int i = digit_shift; i < length; i++) {
result->set_digit(i - digit_shift, x->digit(i));
}
} else {
digit_t carry = x->digit(digit_shift) >> bits_shift;
int last = length - digit_shift - 1;
for (int i = 0; i < last; i++) {
digit_t d = x->digit(i + digit_shift + 1);
result->set_digit(i, (d << (kDigitBits - bits_shift)) | carry);
carry = d >> bits_shift;
}
result->set_digit(last, carry);
}
if (sign) {
result->set_sign(true);
if (must_round_down) {
// Since the result is negative, rounding down means adding one to
// its absolute value.
result = AbsoluteAddOne(result, true, *result);
}
}
result->RightTrim();
return result;
}
Handle<BigInt> BigInt::RightShiftByMaximum(Isolate* isolate, bool sign) {
if (sign) {
// Return -1n.
// TODO(jkummerow): Consider caching a canonical -1n BigInt.
Handle<BigInt> result = isolate->factory()->NewBigInt(1);
result->set_digit(0, 1);
result->set_sign(true);
return result;
} else {
// TODO(jkummerow): Consider caching a canonical zero BigInt.
return isolate->factory()->NewBigInt(0);
}
}
// Returns the value of {x} if it is less than the maximum bit length of
// a BigInt, or Nothing otherwise.
Maybe<BigInt::digit_t> BigInt::ToShiftAmount(Handle<BigInt> x) {
if (x->length() > 1) return Nothing<digit_t>();
digit_t value = x->digit(0);
STATIC_ASSERT(kMaxLength * kDigitBits < std::numeric_limits<digit_t>::max());
if (value > kMaxLength * kDigitBits) return Nothing<digit_t>();
return Just(value);
}
Handle<BigInt> BigInt::Copy(Handle<BigInt> source) { Handle<BigInt> BigInt::Copy(Handle<BigInt> source) {
int length = source->length(); int length = source->length();
Handle<BigInt> result = source->GetIsolate()->factory()->NewBigIntRaw(length); Handle<BigInt> result = source->GetIsolate()->factory()->NewBigIntRaw(length);
......
...@@ -31,8 +31,9 @@ class BigInt : public HeapObject { ...@@ -31,8 +31,9 @@ class BigInt : public HeapObject {
static MaybeHandle<BigInt> Remainder(Handle<BigInt> x, Handle<BigInt> y); static MaybeHandle<BigInt> Remainder(Handle<BigInt> x, Handle<BigInt> y);
static Handle<BigInt> Add(Handle<BigInt> x, Handle<BigInt> y); static Handle<BigInt> Add(Handle<BigInt> x, Handle<BigInt> y);
static Handle<BigInt> Subtract(Handle<BigInt> x, Handle<BigInt> y); static Handle<BigInt> Subtract(Handle<BigInt> x, Handle<BigInt> y);
static Handle<BigInt> LeftShift(Handle<BigInt> x, Handle<BigInt> y); static MaybeHandle<BigInt> LeftShift(Handle<BigInt> x, Handle<BigInt> y);
static Handle<BigInt> SignedRightShift(Handle<BigInt> x, Handle<BigInt> y); static MaybeHandle<BigInt> SignedRightShift(Handle<BigInt> x,
Handle<BigInt> y);
static MaybeHandle<BigInt> UnsignedRightShift(Handle<BigInt> x, static MaybeHandle<BigInt> UnsignedRightShift(Handle<BigInt> x,
Handle<BigInt> y); Handle<BigInt> y);
static bool LessThan(Handle<BigInt> x, Handle<BigInt> y); static bool LessThan(Handle<BigInt> x, Handle<BigInt> y);
...@@ -146,6 +147,14 @@ class BigInt : public HeapObject { ...@@ -146,6 +147,14 @@ class BigInt : public HeapObject {
static Handle<BigInt> SpecialLeftShift(Handle<BigInt> x, int shift, static Handle<BigInt> SpecialLeftShift(Handle<BigInt> x, int shift,
SpecialLeftShiftMode mode); SpecialLeftShiftMode mode);
// Specialized helpers for shift operations.
static MaybeHandle<BigInt> LeftShiftByAbsolute(Handle<BigInt> x,
Handle<BigInt> y);
static Handle<BigInt> RightShiftByAbsolute(Handle<BigInt> x,
Handle<BigInt> y);
static Handle<BigInt> RightShiftByMaximum(Isolate* isolate, bool sign);
static Maybe<digit_t> ToShiftAmount(Handle<BigInt> x);
static MaybeHandle<String> ToStringBasePowerOfTwo(Handle<BigInt> x, static MaybeHandle<String> ToStringBasePowerOfTwo(Handle<BigInt> x,
int radix); int radix);
......
...@@ -428,7 +428,7 @@ bytecodes: [ ...@@ -428,7 +428,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(18), B(Star), R(18),
B(LdaConstant), U8(16), B(LdaConstant), U8(16),
B(Star), R(19), B(Star), R(19),
......
...@@ -143,7 +143,7 @@ bytecodes: [ ...@@ -143,7 +143,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(19), B(Star), R(19),
B(LdaConstant), U8(13), B(LdaConstant), U8(13),
B(Star), R(20), B(Star), R(20),
...@@ -432,7 +432,7 @@ bytecodes: [ ...@@ -432,7 +432,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(19), B(Star), R(19),
B(LdaConstant), U8(13), B(LdaConstant), U8(13),
B(Star), R(20), B(Star), R(20),
...@@ -743,7 +743,7 @@ bytecodes: [ ...@@ -743,7 +743,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(19), B(Star), R(19),
B(LdaConstant), U8(13), B(LdaConstant), U8(13),
B(Star), R(20), B(Star), R(20),
...@@ -991,7 +991,7 @@ bytecodes: [ ...@@ -991,7 +991,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(16), B(Star), R(16),
B(LdaConstant), U8(10), B(LdaConstant), U8(10),
B(Star), R(17), B(Star), R(17),
......
...@@ -86,7 +86,7 @@ bytecodes: [ ...@@ -86,7 +86,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(11), B(Star), R(11),
B(LdaConstant), U8(8), B(LdaConstant), U8(8),
B(Star), R(12), B(Star), R(12),
...@@ -227,7 +227,7 @@ bytecodes: [ ...@@ -227,7 +227,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(12), B(Star), R(12),
B(LdaConstant), U8(8), B(LdaConstant), U8(8),
B(Star), R(13), B(Star), R(13),
...@@ -380,7 +380,7 @@ bytecodes: [ ...@@ -380,7 +380,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(11), B(Star), R(11),
B(LdaConstant), U8(8), B(LdaConstant), U8(8),
B(Star), R(12), B(Star), R(12),
...@@ -523,7 +523,7 @@ bytecodes: [ ...@@ -523,7 +523,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(10), B(Star), R(10),
B(LdaConstant), U8(10), B(LdaConstant), U8(10),
B(Star), R(11), B(Star), R(11),
......
...@@ -90,7 +90,7 @@ bytecodes: [ ...@@ -90,7 +90,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(13), B(Star), R(13),
B(LdaConstant), U8(7), B(LdaConstant), U8(7),
B(Star), R(14), B(Star), R(14),
...@@ -268,7 +268,7 @@ bytecodes: [ ...@@ -268,7 +268,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(13), B(Star), R(13),
B(LdaConstant), U8(11), B(LdaConstant), U8(11),
B(Star), R(14), B(Star), R(14),
...@@ -422,7 +422,7 @@ bytecodes: [ ...@@ -422,7 +422,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(11), B(Star), R(11),
B(LdaConstant), U8(9), B(LdaConstant), U8(9),
B(Star), R(12), B(Star), R(12),
...@@ -524,7 +524,7 @@ bytecodes: [ ...@@ -524,7 +524,7 @@ bytecodes: [
B(JumpIfUndefined), U8(6), B(JumpIfUndefined), U8(6),
B(Ldar), R(6), B(Ldar), R(6),
B(JumpIfNotNull), U8(16), B(JumpIfNotNull), U8(16),
B(LdaSmi), I8(65), B(LdaSmi), I8(66),
B(Star), R(17), B(Star), R(17),
B(LdaConstant), U8(4), B(LdaConstant), U8(4),
B(Star), R(18), B(Star), R(18),
...@@ -580,7 +580,7 @@ bytecodes: [ ...@@ -580,7 +580,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(16), B(Star), R(16),
B(LdaConstant), U8(9), B(LdaConstant), U8(9),
B(Star), R(17), B(Star), R(17),
...@@ -754,7 +754,7 @@ bytecodes: [ ...@@ -754,7 +754,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(16), B(Star), R(16),
B(LdaConstant), U8(10), B(LdaConstant), U8(10),
B(Star), R(17), B(Star), R(17),
...@@ -953,7 +953,7 @@ bytecodes: [ ...@@ -953,7 +953,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(15), B(Star), R(15),
B(LdaConstant), U8(14), B(LdaConstant), U8(14),
B(Star), R(16), B(Star), R(16),
...@@ -1116,7 +1116,7 @@ bytecodes: [ ...@@ -1116,7 +1116,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(20), B(Star), R(20),
B(LdaConstant), U8(7), B(LdaConstant), U8(7),
B(Star), R(21), B(Star), R(21),
...@@ -1358,7 +1358,7 @@ bytecodes: [ ...@@ -1358,7 +1358,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(20), B(Star), R(20),
B(LdaConstant), U8(9), B(LdaConstant), U8(9),
B(Star), R(21), B(Star), R(21),
......
...@@ -257,7 +257,7 @@ bytecodes: [ ...@@ -257,7 +257,7 @@ bytecodes: [
B(TestTypeOf), U8(5), B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(136), B(Wide), B(LdaSmi), I16(137),
B(Star), R(14), B(Star), R(14),
B(LdaConstant), U8(15), B(LdaConstant), U8(15),
B(Star), R(15), B(Star), R(15),
......
...@@ -231,7 +231,7 @@ bytecodes: [ ...@@ -231,7 +231,7 @@ bytecodes: [
B(JumpIfUndefined), U8(6), B(JumpIfUndefined), U8(6),
B(Ldar), R(3), B(Ldar), R(3),
B(JumpIfNotNull), U8(16), B(JumpIfNotNull), U8(16),
B(LdaSmi), I8(65), B(LdaSmi), I8(66),
B(Star), R(4), B(Star), R(4),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(5), B(Star), R(5),
......
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