Index: runtime/lib/integers.cc |
=================================================================== |
--- runtime/lib/integers.cc (revision 3410) |
+++ runtime/lib/integers.cc (working copy) |
@@ -68,20 +68,6 @@ |
} |
-static bool Are63bitOperands(const Integer& op1, const Integer& op2) { |
- if (op1.IsBigint() || op2.IsBigint()) { |
- return false; |
- } |
- const int64_t limit = (static_cast<int64_t>(1)) << 62; |
- const int64_t value1 = op1.AsInt64Value(); |
- if ((-limit > value1) || (value1 >= limit)) { |
- return false; |
- } |
- const int64_t value2 = op2.AsInt64Value(); |
- return (-limit <= value2) && (value2 < limit); |
-} |
- |
- |
static RawInteger* IntegerBitOperation(Token::Kind kind, |
const Integer& op1_int, |
const Integer& op2_int) { |
@@ -240,10 +226,12 @@ |
static RawInteger* IntegerBinopHelper(Token::Kind operation, |
const Integer& left_int, |
const Integer& right_int) { |
- // The result of any operation (except multiplication in 64-bit mode) between |
- // two Smis will always fit in a 64-bit signed result (no overflow). |
- if (((Smi::kBits < 32) || (operation != Token::kMUL)) && |
- left_int.IsSmi() && right_int.IsSmi()) { |
+ // 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). |
+ if (left_int.IsSmi() && right_int.IsSmi()) { |
Smi& left_smi = Smi::Handle(); |
Smi& right_smi = Smi::Handle(); |
left_smi ^= left_int.raw(); |
@@ -256,9 +244,20 @@ |
case Token::kSUB: |
return Integer::New(left_value - right_value); |
case Token::kMUL: { |
- ASSERT(Smi::kBits < 32); // Do not use this code in 64-bit mode. |
- return Integer::New(static_cast<int64_t>(left_value) * |
- static_cast<int64_t>(right_value)); |
+ if (Smi::kBits < 32) { |
+ // In 32-bit mode, the product of two Smis fits in a 64-bit result. |
+ 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. |
+ ASSERT(sizeof(intptr_t) == sizeof(int64_t)); |
+ if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { |
+ return Integer::New(left_value * right_value); |
+ } |
+ } |
+ // Perform a Bigint multiplication below. |
+ break; |
} |
case Token::kTRUNCDIV: |
return Integer::New(left_value / right_value); |
@@ -270,47 +269,51 @@ |
} else { |
return Integer::New(remainder + right_value); |
} |
- } else { |
- return Integer::New(remainder); |
} |
+ return Integer::New(remainder); |
} |
default: |
UNIMPLEMENTED(); |
} |
- UNREACHABLE(); |
- return Integer::null(); |
} |
- // The result of any operation (except multiplication) between two 63-bit |
- // signed integers will fit in a 64-bit signed result. |
- // In 64-bit mode, this case was already handled above. |
- if ((Smi::kBits < 32) && (operation != Token::kMUL) && |
- Are63bitOperands(left_int, right_int)) { |
+ // 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 64-bit mode, 63-bit signed integers are Smis, already processed above. |
+ if ((Smi::kBits < 32) && !left_int.IsBigint() && !right_int.IsBigint()) { |
const int64_t left_value = left_int.AsInt64Value(); |
- const int64_t right_value = right_int.AsInt64Value(); |
- 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); |
+ if (Utils::IsInt(63, left_value)) { |
+ const int64_t right_value = right_int.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); |
} |
- } else { |
+ // 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(); |
+ } |
} |
- default: |
- UNIMPLEMENTED(); |
} |
- UNREACHABLE(); |
- return Integer::null(); |
} |
const Bigint& left_big = Bigint::Handle(AsBigint(left_int)); |
const Bigint& right_big = Bigint::Handle(AsBigint(right_int)); |