| Index: runtime/vm/object.cc
|
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
|
| index 356e1a5b7a816cc802af76037dba8bc9e4a6f5bf..6a63bed3636c75909e58f10a784c9419b208c826 100644
|
| --- a/runtime/vm/object.cc
|
| +++ b/runtime/vm/object.cc
|
| @@ -8808,8 +8808,8 @@ RawInteger* Integer::AsInteger() const {
|
| }
|
|
|
|
|
| -RawInteger* Integer::BinaryOp(Token::Kind operation,
|
| - const Integer& other) const {
|
| +RawInteger* Integer::ArithmeticOp(Token::Kind operation,
|
| + const Integer& other) const {
|
| // 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
|
| @@ -8902,11 +8902,109 @@ RawInteger* Integer::BinaryOp(Token::Kind operation,
|
| const Bigint& left_big = Bigint::Handle(AsBigint());
|
| const Bigint& right_big = Bigint::Handle(other.AsBigint());
|
| const Bigint& result =
|
| - Bigint::Handle(left_big.BinaryOp(operation, right_big));
|
| + Bigint::Handle(left_big.ArithmeticOp(operation, right_big));
|
| return Integer::Handle(result.AsInteger()).raw();
|
| }
|
|
|
|
|
| +static bool Are64bitOperands(const Integer& op1, const Integer& op2) {
|
| + return !op1.IsBigint() && !op2.IsBigint();
|
| +}
|
| +
|
| +
|
| +RawInteger* Integer::BitOp(Token::Kind kind, const Integer& other) const {
|
| + if (IsSmi() && other.IsSmi()) {
|
| + Smi& op1 = Smi::Handle();
|
| + Smi& op2 = Smi::Handle();
|
| + op1 ^= raw();
|
| + op2 ^= other.raw();
|
| + intptr_t result = 0;
|
| + switch (kind) {
|
| + case Token::kBIT_AND:
|
| + result = op1.Value() & op2.Value();
|
| + break;
|
| + case Token::kBIT_OR:
|
| + result = op1.Value() | op2.Value();
|
| + break;
|
| + case Token::kBIT_XOR:
|
| + result = op1.Value() ^ op2.Value();
|
| + break;
|
| + default:
|
| + UNIMPLEMENTED();
|
| + }
|
| + ASSERT(Smi::IsValid(result));
|
| + return Smi::New(result);
|
| + } else if (Are64bitOperands(*this, other)) {
|
| + int64_t a = AsInt64Value();
|
| + int64_t b = other.AsInt64Value();
|
| + switch (kind) {
|
| + case Token::kBIT_AND:
|
| + return Integer::New(a & b);
|
| + case Token::kBIT_OR:
|
| + return Integer::New(a | b);
|
| + case Token::kBIT_XOR:
|
| + return Integer::New(a ^ b);
|
| + default:
|
| + UNIMPLEMENTED();
|
| + }
|
| + } else {
|
| + Bigint& op1 = Bigint::Handle(AsBigint());
|
| + Bigint& op2 = Bigint::Handle(other.AsBigint());
|
| + switch (kind) {
|
| + case Token::kBIT_AND:
|
| + return BigintOperations::BitAnd(op1, op2);
|
| + case Token::kBIT_OR:
|
| + return BigintOperations::BitOr(op1, op2);
|
| + case Token::kBIT_XOR:
|
| + return BigintOperations::BitXor(op1, op2);
|
| + default:
|
| + UNIMPLEMENTED();
|
| + }
|
| + }
|
| + return Integer::null();
|
| +}
|
| +
|
| +
|
| +// TODO(srdjan): Clarify handling of negative right operand in a shift op.
|
| +RawInteger* Smi::ShiftOp(Token::Kind kind, const Smi& other) const {
|
| + intptr_t result = 0;
|
| + const intptr_t left_value = Value();
|
| + const intptr_t right_value = other.Value();
|
| + ASSERT(right_value >= 0);
|
| + switch (kind) {
|
| + case Token::kSHL: {
|
| + if ((left_value == 0) || (right_value == 0)) {
|
| + return raw();
|
| + }
|
| + { // Check for overflow.
|
| + int cnt = Utils::HighestBit(left_value);
|
| + if ((cnt + right_value) >= Smi::kBits) {
|
| + if ((cnt + right_value) >= Mint::kBits) {
|
| + return BigintOperations::ShiftLeft(
|
| + Bigint::Handle(AsBigint()), right_value);
|
| + } else {
|
| + int64_t left_64 = left_value;
|
| + return Integer::New(left_64 << right_value);
|
| + }
|
| + }
|
| + }
|
| + result = left_value << right_value;
|
| + break;
|
| + }
|
| + case Token::kSHR: {
|
| + const intptr_t shift_amount =
|
| + (right_value >= kBitsPerWord) ? (kBitsPerWord - 1) : right_value;
|
| + result = left_value >> shift_amount;
|
| + break;
|
| + }
|
| + default:
|
| + UNIMPLEMENTED();
|
| + }
|
| + ASSERT(Smi::IsValid(result));
|
| + return Smi::New(result);
|
| +}
|
| +
|
| +
|
| bool Smi::Equals(const Instance& other) const {
|
| if (other.IsNull() || !other.IsSmi()) {
|
| return false;
|
| @@ -9229,7 +9327,8 @@ RawBigint* Integer::AsBigint() const {
|
| }
|
|
|
|
|
| -RawBigint* Bigint::BinaryOp(Token::Kind operation, const Bigint& other) const {
|
| +RawBigint* Bigint::ArithmeticOp(Token::Kind operation,
|
| + const Bigint& other) const {
|
| switch (operation) {
|
| case Token::kADD:
|
| return BigintOperations::Add(*this, other);
|
|
|