OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/object.h" | 5 #include "vm/object.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 15210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15221 return big_value.raw(); | 15221 return big_value.raw(); |
15222 } | 15222 } |
15223 } | 15223 } |
15224 | 15224 |
15225 | 15225 |
15226 RawInteger* Integer::ArithmeticOp(Token::Kind operation, | 15226 RawInteger* Integer::ArithmeticOp(Token::Kind operation, |
15227 const Integer& other) const { | 15227 const Integer& other) const { |
15228 // In 32-bit mode, the result of any operation between two Smis will fit in a | 15228 // In 32-bit mode, the result of any operation between two Smis will fit in a |
15229 // 32-bit signed result, except the product of two Smis, which will be 64-bit. | 15229 // 32-bit signed result, except the product of two Smis, which will be 64-bit. |
15230 // In 64-bit mode, the result of any operation between two Smis will fit in a | 15230 // In 64-bit mode, the result of any operation between two Smis will fit in a |
15231 // 64-bit signed result, except the product of two Smis (unless the Smis are | 15231 // 64-bit signed result, except the product of two Smis (see below). |
15232 // 32-bit or less). | |
15233 if (IsSmi() && other.IsSmi()) { | 15232 if (IsSmi() && other.IsSmi()) { |
15234 const intptr_t left_value = Smi::Value(Smi::RawCast(raw())); | 15233 const intptr_t left_value = Smi::Value(Smi::RawCast(raw())); |
15235 const intptr_t right_value = Smi::Value(Smi::RawCast(other.raw())); | 15234 const intptr_t right_value = Smi::Value(Smi::RawCast(other.raw())); |
15236 switch (operation) { | 15235 switch (operation) { |
15237 case Token::kADD: | 15236 case Token::kADD: |
15238 return Integer::New(left_value + right_value); | 15237 return Integer::New(left_value + right_value); |
15239 case Token::kSUB: | 15238 case Token::kSUB: |
15240 return Integer::New(left_value - right_value); | 15239 return Integer::New(left_value - right_value); |
15241 case Token::kMUL: { | 15240 case Token::kMUL: { |
15242 if (Smi::kBits < 32) { | 15241 if (Smi::kBits < 32) { |
15243 // In 32-bit mode, the product of two Smis fits in a 64-bit result. | 15242 // In 32-bit mode, the product of two Smis fits in a 64-bit result. |
15244 return Integer::New(static_cast<int64_t>(left_value) * | 15243 return Integer::New(static_cast<int64_t>(left_value) * |
15245 static_cast<int64_t>(right_value)); | 15244 static_cast<int64_t>(right_value)); |
15246 } else { | 15245 } else { |
15247 // In 64-bit mode, the product of two 32-bit signed integers fits in a | 15246 // In 64-bit mode, the product of two signed integers fits in a |
15248 // 64-bit result. | 15247 // 64-bit result if the sum of the highest bits of their absolute |
| 15248 // values is smaller than 62. |
15249 ASSERT(sizeof(intptr_t) == sizeof(int64_t)); | 15249 ASSERT(sizeof(intptr_t) == sizeof(int64_t)); |
15250 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { | 15250 if ((Utils::HighestBit(left_value) + |
| 15251 Utils::HighestBit(right_value)) < 62) { |
15251 return Integer::New(left_value * right_value); | 15252 return Integer::New(left_value * right_value); |
15252 } | 15253 } |
15253 } | 15254 } |
15254 // Perform a Bigint multiplication below. | 15255 // Perform a Bigint multiplication below. |
15255 break; | 15256 break; |
15256 } | 15257 } |
15257 case Token::kTRUNCDIV: | 15258 case Token::kTRUNCDIV: |
15258 return Integer::New(left_value / right_value); | 15259 return Integer::New(left_value / right_value); |
15259 case Token::kMOD: { | 15260 case Token::kMOD: { |
15260 const intptr_t remainder = left_value % right_value; | 15261 const intptr_t remainder = left_value % right_value; |
15261 if (remainder < 0) { | 15262 if (remainder < 0) { |
15262 if (right_value < 0) { | 15263 if (right_value < 0) { |
15263 return Integer::New(remainder - right_value); | 15264 return Integer::New(remainder - right_value); |
15264 } else { | 15265 } else { |
15265 return Integer::New(remainder + right_value); | 15266 return Integer::New(remainder + right_value); |
15266 } | 15267 } |
15267 } | 15268 } |
15268 return Integer::New(remainder); | 15269 return Integer::New(remainder); |
15269 } | 15270 } |
15270 default: | 15271 default: |
15271 UNIMPLEMENTED(); | 15272 UNIMPLEMENTED(); |
15272 } | 15273 } |
15273 } | 15274 } |
15274 // In 32-bit mode, the result of any operation between two 63-bit signed | 15275 // In 32-bit mode, the result of any operation (except multiplication) between |
15275 // integers (or 32-bit for multiplication) will fit in a 64-bit signed result. | 15276 // two 63-bit signed integers will fit in a 64-bit signed result. |
| 15277 // For the multiplication result to fit, the sum of the highest bits of the |
| 15278 // absolute values of the operands must be smaller than 62. |
15276 // In 64-bit mode, 63-bit signed integers are Smis, already processed above. | 15279 // In 64-bit mode, 63-bit signed integers are Smis, already processed above. |
15277 if ((Smi::kBits < 32) && !IsBigint() && !other.IsBigint()) { | 15280 if ((Smi::kBits < 32) && !IsBigint() && !other.IsBigint()) { |
15278 const int64_t left_value = AsInt64Value(); | 15281 const int64_t left_value = AsInt64Value(); |
15279 if (Utils::IsInt(63, left_value)) { | 15282 const int64_t right_value = other.AsInt64Value(); |
15280 const int64_t right_value = other.AsInt64Value(); | 15283 if (operation == Token::kMUL) { |
15281 if (Utils::IsInt(63, right_value)) { | 15284 if ((Utils::HighestBit(left_value) + |
15282 switch (operation) { | 15285 Utils::HighestBit(right_value)) < 62) { |
15283 case Token::kADD: | 15286 return Integer::New(left_value * right_value); |
15284 return Integer::New(left_value + right_value); | 15287 } |
15285 case Token::kSUB: | 15288 // Perform a Bigint multiplication below. |
15286 return Integer::New(left_value - right_value); | 15289 } else if (Utils::IsInt(63, left_value) && Utils::IsInt(63, right_value)) { |
15287 case Token::kMUL: { | 15290 switch (operation) { |
15288 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { | 15291 case Token::kADD: |
15289 return Integer::New(left_value * right_value); | 15292 return Integer::New(left_value + right_value); |
| 15293 case Token::kSUB: |
| 15294 return Integer::New(left_value - right_value); |
| 15295 case Token::kTRUNCDIV: |
| 15296 return Integer::New(left_value / right_value); |
| 15297 case Token::kMOD: { |
| 15298 const int64_t remainder = left_value % right_value; |
| 15299 if (remainder < 0) { |
| 15300 if (right_value < 0) { |
| 15301 return Integer::New(remainder - right_value); |
| 15302 } else { |
| 15303 return Integer::New(remainder + right_value); |
15290 } | 15304 } |
15291 // Perform a Bigint multiplication below. | |
15292 break; | |
15293 } | 15305 } |
15294 case Token::kTRUNCDIV: | 15306 return Integer::New(remainder); |
15295 return Integer::New(left_value / right_value); | 15307 } |
15296 case Token::kMOD: { | 15308 default: |
15297 const int64_t remainder = left_value % right_value; | 15309 UNIMPLEMENTED(); |
15298 if (remainder < 0) { | |
15299 if (right_value < 0) { | |
15300 return Integer::New(remainder - right_value); | |
15301 } else { | |
15302 return Integer::New(remainder + right_value); | |
15303 } | |
15304 } | |
15305 return Integer::New(remainder); | |
15306 } | |
15307 default: | |
15308 UNIMPLEMENTED(); | |
15309 } | |
15310 } | 15310 } |
15311 } | 15311 } |
15312 } | 15312 } |
15313 const Bigint& left_big = Bigint::Handle(AsBigint()); | 15313 const Bigint& left_big = Bigint::Handle(AsBigint()); |
15314 const Bigint& right_big = Bigint::Handle(other.AsBigint()); | 15314 const Bigint& right_big = Bigint::Handle(other.AsBigint()); |
15315 const Bigint& result = | 15315 const Bigint& result = |
15316 Bigint::Handle(left_big.BigArithmeticOp(operation, right_big)); | 15316 Bigint::Handle(left_big.BigArithmeticOp(operation, right_big)); |
15317 return Integer::Handle(result.AsValidInteger()).raw(); | 15317 return Integer::Handle(result.AsValidInteger()).raw(); |
15318 } | 15318 } |
15319 | 15319 |
(...skipping 3734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19054 return tag_label.ToCString(); | 19054 return tag_label.ToCString(); |
19055 } | 19055 } |
19056 | 19056 |
19057 | 19057 |
19058 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 19058 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
19059 Instance::PrintJSONImpl(stream, ref); | 19059 Instance::PrintJSONImpl(stream, ref); |
19060 } | 19060 } |
19061 | 19061 |
19062 | 19062 |
19063 } // namespace dart | 19063 } // namespace dart |
OLD | NEW |