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 |