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 return left.Value() + right.Value(); | 212 return left.Value() + right.Value(); |
cshapiro
2011/12/17 00:09:44
This needs an overflow check for 64-bit.
regis
2011/12/17 00:47:44
I think we are fine here, because both operands ar
| |
213 case Token::kSUB: | 213 case Token::kSUB: |
214 return left.Value() - right.Value(); | 214 return left.Value() - right.Value(); |
215 case Token::kMUL: { | 215 case Token::kMUL: { |
216 #if defined(TARGET_ARCH_X64) | 216 const Bigint& big_left = |
cshapiro
2011/12/17 00:09:44
This needs a TODO since it may cause a performance
regis
2011/12/17 00:47:44
Done.
| |
217 // Overflow check for 64-bit platforms unimplemented. | 217 Bigint::Handle(BigintOperations::NewFromSmi(left)); |
218 UNIMPLEMENTED(); | 218 const Bigint& big_right = |
219 return 0; | 219 Bigint::Handle(BigintOperations::NewFromSmi(right)); |
220 #else | 220 const Bigint& big_result = |
221 int64_t result_64 = | 221 Bigint::Handle(BigintOperations::Multiply(big_left, big_right)); |
222 static_cast<int64_t>(left.Value()) * | 222 if (BigintOperations::FitsIntoInt64(big_result)) { |
223 static_cast<int64_t>(right.Value()); | 223 return BigintOperations::ToInt64(big_result); |
224 return result_64; | 224 } else { |
225 #endif | 225 // Overflow, return an invalid Smi. |
226 return Smi::kMaxValue + 1; | |
227 } | |
226 } | 228 } |
227 case Token::kTRUNCDIV: | 229 case Token::kTRUNCDIV: |
228 return left.Value() / right.Value(); | 230 return left.Value() / right.Value(); |
229 case Token::kMOD: { | 231 case Token::kMOD: { |
230 intptr_t remainder = left.Value() % right.Value(); | 232 intptr_t remainder = left.Value() % right.Value(); |
231 if (remainder < 0) { | 233 if (remainder < 0) { |
232 if (right.Value() < 0) { | 234 if (right.Value() < 0) { |
233 return remainder - right.Value(); | 235 return remainder - right.Value(); |
234 } else { | 236 } else { |
235 return remainder + right.Value(); | 237 return remainder + right.Value(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
278 const Integer& right_int) { | 280 const Integer& right_int) { |
279 if (left_int.IsSmi() && right_int.IsSmi()) { | 281 if (left_int.IsSmi() && right_int.IsSmi()) { |
280 Smi& left_smi = Smi::Handle(); | 282 Smi& left_smi = Smi::Handle(); |
281 Smi& right_smi = Smi::Handle(); | 283 Smi& right_smi = Smi::Handle(); |
282 left_smi ^= left_int.raw(); | 284 left_smi ^= left_int.raw(); |
283 right_smi ^= right_int.raw(); | 285 right_smi ^= right_int.raw(); |
284 int64_t result = BinaryOpWithTwoSmis(operation, left_smi, right_smi); | 286 int64_t result = BinaryOpWithTwoSmis(operation, left_smi, right_smi); |
285 if (Smi::IsValid64(result)) { | 287 if (Smi::IsValid64(result)) { |
286 return Smi::New(result); | 288 return Smi::New(result); |
287 } else { | 289 } else { |
290 // TODO(regis): This is not going to work on x64. Check other operations. | |
291 #if defined(TARGET_ARCH_X64) | |
292 UNIMPLEMENTED(); | |
293 return 0; | |
294 #else | |
288 // Overflow to Mint. | 295 // Overflow to Mint. |
289 return Mint::New(result); | 296 return Mint::New(result); |
297 #endif | |
290 } | 298 } |
291 } else if (AreBoth64bitOperands(left_int, right_int)) { | 299 } else if (AreBoth64bitOperands(left_int, right_int)) { |
292 // TODO(srdjan): Test for overflow of result instead of operand | 300 // TODO(srdjan): Test for overflow of result instead of operand |
293 // types. | 301 // types. |
294 const int64_t a = left_int.AsInt64Value(); | 302 const int64_t a = left_int.AsInt64Value(); |
295 const int64_t b = right_int.AsInt64Value(); | 303 const int64_t b = right_int.AsInt64Value(); |
296 switch (operation) { | 304 switch (operation) { |
297 case Token::kADD: | 305 case Token::kADD: |
298 return Integer::New(a + b); | 306 return Integer::New(a + b); |
299 case Token::kSUB: | 307 case Token::kSUB: |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
579 | 587 |
580 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { | 588 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { |
581 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); | 589 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); |
582 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); | 590 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); |
583 ASSERT(CheckInteger(value)); | 591 ASSERT(CheckInteger(value)); |
584 ASSERT(CheckInteger(result)); | 592 ASSERT(CheckInteger(result)); |
585 arguments->SetReturn(Integer::Handle(AsInteger(result))); | 593 arguments->SetReturn(Integer::Handle(AsInteger(result))); |
586 } | 594 } |
587 | 595 |
588 } // namespace dart | 596 } // namespace dart |
OLD | NEW |