| Index: runtime/vm/object.cc
|
| ===================================================================
|
| --- runtime/vm/object.cc (revision 38076)
|
| +++ runtime/vm/object.cc (working copy)
|
| @@ -15228,8 +15228,7 @@
|
| // In 32-bit mode, the result of any operation between two Smis will fit in a
|
| // 32-bit signed result, except the product of two Smis, which will be 64-bit.
|
| // In 64-bit mode, the result of any operation between two Smis will fit in a
|
| - // 64-bit signed result, except the product of two Smis (unless the Smis are
|
| - // 32-bit or less).
|
| + // 64-bit signed result, except the product of two Smis (see below).
|
| if (IsSmi() && other.IsSmi()) {
|
| const intptr_t left_value = Smi::Value(Smi::RawCast(raw()));
|
| const intptr_t right_value = Smi::Value(Smi::RawCast(other.raw()));
|
| @@ -15244,10 +15243,12 @@
|
| return Integer::New(static_cast<int64_t>(left_value) *
|
| static_cast<int64_t>(right_value));
|
| } else {
|
| - // In 64-bit mode, the product of two 32-bit signed integers fits in a
|
| - // 64-bit result.
|
| + // In 64-bit mode, the product of two signed integers fits in a
|
| + // 64-bit result if the sum of the highest bits of their absolute
|
| + // values is smaller than 62.
|
| ASSERT(sizeof(intptr_t) == sizeof(int64_t));
|
| - if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) {
|
| + if ((Utils::HighestBit(left_value) +
|
| + Utils::HighestBit(right_value)) < 62) {
|
| return Integer::New(left_value * right_value);
|
| }
|
| }
|
| @@ -15271,43 +15272,42 @@
|
| UNIMPLEMENTED();
|
| }
|
| }
|
| - // In 32-bit mode, the result of any operation between two 63-bit signed
|
| - // integers (or 32-bit for multiplication) will fit in a 64-bit signed result.
|
| + // In 32-bit mode, the result of any operation (except multiplication) between
|
| + // two 63-bit signed integers will fit in a 64-bit signed result.
|
| + // For the multiplication result to fit, the sum of the highest bits of the
|
| + // absolute values of the operands must be smaller than 62.
|
| // In 64-bit mode, 63-bit signed integers are Smis, already processed above.
|
| if ((Smi::kBits < 32) && !IsBigint() && !other.IsBigint()) {
|
| const int64_t left_value = AsInt64Value();
|
| - if (Utils::IsInt(63, left_value)) {
|
| - const int64_t right_value = other.AsInt64Value();
|
| - if (Utils::IsInt(63, right_value)) {
|
| - switch (operation) {
|
| - case Token::kADD:
|
| - return Integer::New(left_value + right_value);
|
| - case Token::kSUB:
|
| - return Integer::New(left_value - right_value);
|
| - case Token::kMUL: {
|
| - if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) {
|
| - return Integer::New(left_value * right_value);
|
| + const int64_t right_value = other.AsInt64Value();
|
| + if (operation == Token::kMUL) {
|
| + if ((Utils::HighestBit(left_value) +
|
| + Utils::HighestBit(right_value)) < 62) {
|
| + return Integer::New(left_value * right_value);
|
| + }
|
| + // Perform a Bigint multiplication below.
|
| + } else if (Utils::IsInt(63, left_value) && Utils::IsInt(63, right_value)) {
|
| + switch (operation) {
|
| + case Token::kADD:
|
| + return Integer::New(left_value + right_value);
|
| + case Token::kSUB:
|
| + return Integer::New(left_value - right_value);
|
| + case Token::kTRUNCDIV:
|
| + return Integer::New(left_value / right_value);
|
| + case Token::kMOD: {
|
| + const int64_t remainder = left_value % right_value;
|
| + if (remainder < 0) {
|
| + if (right_value < 0) {
|
| + return Integer::New(remainder - right_value);
|
| + } else {
|
| + return Integer::New(remainder + right_value);
|
| }
|
| - // Perform a Bigint multiplication below.
|
| - break;
|
| }
|
| - case Token::kTRUNCDIV:
|
| - return Integer::New(left_value / right_value);
|
| - case Token::kMOD: {
|
| - const int64_t remainder = left_value % right_value;
|
| - if (remainder < 0) {
|
| - if (right_value < 0) {
|
| - return Integer::New(remainder - right_value);
|
| - } else {
|
| - return Integer::New(remainder + right_value);
|
| - }
|
| - }
|
| - return Integer::New(remainder);
|
| - }
|
| - default:
|
| - UNIMPLEMENTED();
|
| - }
|
| + return Integer::New(remainder);
|
| }
|
| + default:
|
| + UNIMPLEMENTED();
|
| + }
|
| }
|
| }
|
| const Bigint& left_big = Bigint::Handle(AsBigint());
|
|
|