| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/bootstrap_natives.h" | 5 #include "vm/bootstrap_natives.h" |
| 6 | 6 |
| 7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/exceptions.h" | 9 #include "vm/exceptions.h" |
| 10 #include "vm/native_entry.h" | 10 #include "vm/native_entry.h" |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", | 196 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", |
| 197 left.ToCString(), right.ToCString()); | 197 left.ToCString(), right.ToCString()); |
| 198 } | 198 } |
| 199 Integer& result = Integer::Handle( | 199 Integer& result = Integer::Handle( |
| 200 IntegerBitOperation(Token::kBIT_XOR, left, right)); | 200 IntegerBitOperation(Token::kBIT_XOR, left, right)); |
| 201 arguments->SetReturn(Integer::Handle(AsInteger(result))); | 201 arguments->SetReturn(Integer::Handle(AsInteger(result))); |
| 202 } | 202 } |
| 203 | 203 |
| 204 | 204 |
| 205 // The result is invalid if it is outside the range | 205 // The result is invalid if it is outside the range |
| 206 // Smi::kMaxValue..Smi::kMinValue. | 206 // Smi::kMinValue..Smi::kMaxValue. |
| 207 static int64_t BinaryOpWithTwoSmis(Token::Kind operation, | 207 static int64_t BinaryOpWithTwoSmis(Token::Kind operation, |
| 208 const Smi& left, | 208 const Smi& left, |
| 209 const Smi& right) { | 209 const Smi& right) { |
| 210 switch (operation) { | 210 switch (operation) { |
| 211 case Token::kADD: | 211 case Token::kADD: |
| 212 // TODO(regis): We may need an overflow check in 64-bit mode. Revisit. |
| 212 return left.Value() + right.Value(); | 213 return left.Value() + right.Value(); |
| 213 case Token::kSUB: | 214 case Token::kSUB: |
| 214 return left.Value() - right.Value(); | 215 return left.Value() - right.Value(); |
| 215 case Token::kMUL: { | 216 case Token::kMUL: { |
| 216 #if defined(TARGET_ARCH_X64) | 217 // TODO(regis): Using Bigint here may be a performance issue. Revisit. |
| 217 // Overflow check for 64-bit platforms unimplemented. | 218 const Bigint& big_left = |
| 218 UNIMPLEMENTED(); | 219 Bigint::Handle(BigintOperations::NewFromSmi(left)); |
| 219 return 0; | 220 const Bigint& big_right = |
| 220 #else | 221 Bigint::Handle(BigintOperations::NewFromSmi(right)); |
| 221 int64_t result_64 = | 222 const Bigint& big_result = |
| 222 static_cast<int64_t>(left.Value()) * | 223 Bigint::Handle(BigintOperations::Multiply(big_left, big_right)); |
| 223 static_cast<int64_t>(right.Value()); | 224 if (BigintOperations::FitsIntoInt64(big_result)) { |
| 224 return result_64; | 225 return BigintOperations::ToInt64(big_result); |
| 225 #endif | 226 } else { |
| 227 // Overflow, return an invalid Smi. |
| 228 return Smi::kMaxValue + 1; |
| 229 } |
| 226 } | 230 } |
| 227 case Token::kTRUNCDIV: | 231 case Token::kTRUNCDIV: |
| 228 return left.Value() / right.Value(); | 232 return left.Value() / right.Value(); |
| 229 case Token::kMOD: { | 233 case Token::kMOD: { |
| 230 intptr_t remainder = left.Value() % right.Value(); | 234 intptr_t remainder = left.Value() % right.Value(); |
| 231 if (remainder < 0) { | 235 if (remainder < 0) { |
| 232 if (right.Value() < 0) { | 236 if (right.Value() < 0) { |
| 233 return remainder - right.Value(); | 237 return remainder - right.Value(); |
| 234 } else { | 238 } else { |
| 235 return remainder + right.Value(); | 239 return remainder + right.Value(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 const Integer& right_int) { | 282 const Integer& right_int) { |
| 279 if (left_int.IsSmi() && right_int.IsSmi()) { | 283 if (left_int.IsSmi() && right_int.IsSmi()) { |
| 280 Smi& left_smi = Smi::Handle(); | 284 Smi& left_smi = Smi::Handle(); |
| 281 Smi& right_smi = Smi::Handle(); | 285 Smi& right_smi = Smi::Handle(); |
| 282 left_smi ^= left_int.raw(); | 286 left_smi ^= left_int.raw(); |
| 283 right_smi ^= right_int.raw(); | 287 right_smi ^= right_int.raw(); |
| 284 int64_t result = BinaryOpWithTwoSmis(operation, left_smi, right_smi); | 288 int64_t result = BinaryOpWithTwoSmis(operation, left_smi, right_smi); |
| 285 if (Smi::IsValid64(result)) { | 289 if (Smi::IsValid64(result)) { |
| 286 return Smi::New(result); | 290 return Smi::New(result); |
| 287 } else { | 291 } else { |
| 292 // TODO(regis): This is not going to work on x64. Check other operations. |
| 293 #if defined(TARGET_ARCH_X64) |
| 294 UNIMPLEMENTED(); |
| 295 return 0; |
| 296 #else |
| 288 // Overflow to Mint. | 297 // Overflow to Mint. |
| 289 return Mint::New(result); | 298 return Mint::New(result); |
| 299 #endif |
| 290 } | 300 } |
| 291 } else if (AreBoth64bitOperands(left_int, right_int)) { | 301 } else if (AreBoth64bitOperands(left_int, right_int)) { |
| 292 // TODO(srdjan): Test for overflow of result instead of operand | 302 // TODO(srdjan): Test for overflow of result instead of operand |
| 293 // types. | 303 // types. |
| 294 const int64_t a = left_int.AsInt64Value(); | 304 const int64_t a = left_int.AsInt64Value(); |
| 295 const int64_t b = right_int.AsInt64Value(); | 305 const int64_t b = right_int.AsInt64Value(); |
| 296 switch (operation) { | 306 switch (operation) { |
| 297 case Token::kADD: | 307 case Token::kADD: |
| 298 return Integer::New(a + b); | 308 return Integer::New(a + b); |
| 299 case Token::kSUB: | 309 case Token::kSUB: |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 | 589 |
| 580 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { | 590 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { |
| 581 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); | 591 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); |
| 582 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); | 592 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); |
| 583 ASSERT(CheckInteger(value)); | 593 ASSERT(CheckInteger(value)); |
| 584 ASSERT(CheckInteger(result)); | 594 ASSERT(CheckInteger(result)); |
| 585 arguments->SetReturn(Integer::Handle(AsInteger(result))); | 595 arguments->SetReturn(Integer::Handle(AsInteger(result))); |
| 586 } | 596 } |
| 587 | 597 |
| 588 } // namespace dart | 598 } // namespace dart |
| OLD | NEW |