| 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 |