Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: runtime/lib/integers.cc

Issue 9112050: Simplify integer arithmetic code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/platform/utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 return big.raw(); 61 return big.raw();
62 } 62 }
63 } 63 }
64 64
65 65
66 static bool Are64bitOperands(const Integer& op1, const Integer& op2) { 66 static bool Are64bitOperands(const Integer& op1, const Integer& op2) {
67 return !op1.IsBigint() && !op2.IsBigint(); 67 return !op1.IsBigint() && !op2.IsBigint();
68 } 68 }
69 69
70 70
71 static bool Are63bitOperands(const Integer& op1, const Integer& op2) {
72 if (op1.IsBigint() || op2.IsBigint()) {
73 return false;
74 }
75 const int64_t limit = (static_cast<int64_t>(1)) << 62;
76 const int64_t value1 = op1.AsInt64Value();
77 if ((-limit > value1) || (value1 >= limit)) {
78 return false;
79 }
80 const int64_t value2 = op2.AsInt64Value();
81 return (-limit <= value2) && (value2 < limit);
82 }
83
84
85 static RawInteger* IntegerBitOperation(Token::Kind kind, 71 static RawInteger* IntegerBitOperation(Token::Kind kind,
86 const Integer& op1_int, 72 const Integer& op1_int,
87 const Integer& op2_int) { 73 const Integer& op2_int) {
88 if (op1_int.IsSmi() && op2_int.IsSmi()) { 74 if (op1_int.IsSmi() && op2_int.IsSmi()) {
89 Smi& op1 = Smi::Handle(); 75 Smi& op1 = Smi::Handle();
90 Smi& op2 = Smi::Handle(); 76 Smi& op2 = Smi::Handle();
91 op1 ^= op1_int.raw(); 77 op1 ^= op1_int.raw();
92 op2 ^= op2_int.raw(); 78 op2 ^= op2_int.raw();
93 intptr_t result = 0; 79 intptr_t result = 0;
94 switch (kind) { 80 switch (kind) {
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 default: 219 default:
234 UNIMPLEMENTED(); 220 UNIMPLEMENTED();
235 return Bigint::null(); 221 return Bigint::null();
236 } 222 }
237 } 223 }
238 224
239 225
240 static RawInteger* IntegerBinopHelper(Token::Kind operation, 226 static RawInteger* IntegerBinopHelper(Token::Kind operation,
241 const Integer& left_int, 227 const Integer& left_int,
242 const Integer& right_int) { 228 const Integer& right_int) {
243 // The result of any operation (except multiplication in 64-bit mode) between 229 // In 32-bit mode, the result of any operation between two Smis will fit in a
244 // two Smis will always fit in a 64-bit signed result (no overflow). 230 // 32-bit signed result, except the product of two Smis, which will be 64-bit.
245 if (((Smi::kBits < 32) || (operation != Token::kMUL)) && 231 // In 64-bit mode, the result of any operation between two Smis will fit in a
246 left_int.IsSmi() && right_int.IsSmi()) { 232 // 64-bit signed result, except the product of two Smis (unless the Smis are
233 // 32-bit or less).
234 if (left_int.IsSmi() && right_int.IsSmi()) {
247 Smi& left_smi = Smi::Handle(); 235 Smi& left_smi = Smi::Handle();
248 Smi& right_smi = Smi::Handle(); 236 Smi& right_smi = Smi::Handle();
249 left_smi ^= left_int.raw(); 237 left_smi ^= left_int.raw();
250 right_smi ^= right_int.raw(); 238 right_smi ^= right_int.raw();
251 const intptr_t left_value = left_smi.Value(); 239 const intptr_t left_value = left_smi.Value();
252 const intptr_t right_value = right_smi.Value(); 240 const intptr_t right_value = right_smi.Value();
253 switch (operation) { 241 switch (operation) {
254 case Token::kADD: 242 case Token::kADD:
255 return Integer::New(left_value + right_value); 243 return Integer::New(left_value + right_value);
256 case Token::kSUB: 244 case Token::kSUB:
257 return Integer::New(left_value - right_value); 245 return Integer::New(left_value - right_value);
258 case Token::kMUL: { 246 case Token::kMUL: {
259 ASSERT(Smi::kBits < 32); // Do not use this code in 64-bit mode. 247 if (Smi::kBits < 32) {
260 return Integer::New(static_cast<int64_t>(left_value) * 248 // In 32-bit mode, the product of two Smis fits in a 64-bit result.
261 static_cast<int64_t>(right_value)); 249 return Integer::New(static_cast<int64_t>(left_value) *
250 static_cast<int64_t>(right_value));
251 } else {
252 // In 64-bit mode, the product of two 32-bit signed integers fits in a
253 // 64-bit result.
254 ASSERT(sizeof(intptr_t) == sizeof(int64_t));
255 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) {
256 return Integer::New(left_value * right_value);
257 }
258 }
259 // Perform a Bigint multiplication below.
260 break;
262 } 261 }
263 case Token::kTRUNCDIV: 262 case Token::kTRUNCDIV:
264 return Integer::New(left_value / right_value); 263 return Integer::New(left_value / right_value);
265 case Token::kMOD: { 264 case Token::kMOD: {
266 const intptr_t remainder = left_value % right_value; 265 const intptr_t remainder = left_value % right_value;
267 if (remainder < 0) { 266 if (remainder < 0) {
268 if (right_value < 0) { 267 if (right_value < 0) {
269 return Integer::New(remainder - right_value); 268 return Integer::New(remainder - right_value);
270 } else { 269 } else {
271 return Integer::New(remainder + right_value); 270 return Integer::New(remainder + right_value);
272 } 271 }
273 } else {
274 return Integer::New(remainder);
275 } 272 }
273 return Integer::New(remainder);
276 } 274 }
277 default: 275 default:
278 UNIMPLEMENTED(); 276 UNIMPLEMENTED();
279 } 277 }
280 UNREACHABLE();
281 return Integer::null();
282 } 278 }
283 // The result of any operation (except multiplication) between two 63-bit 279 // In 32-bit mode, the result of any operation between two 63-bit signed
284 // signed integers will fit in a 64-bit signed result. 280 // integers (or 32-bit for multiplication) will fit in a 64-bit signed result.
285 // In 64-bit mode, this case was already handled above. 281 // In 64-bit mode, 63-bit signed integers are Smis, already processed above.
286 if ((Smi::kBits < 32) && (operation != Token::kMUL) && 282 if ((Smi::kBits < 32) && !left_int.IsBigint() && !right_int.IsBigint()) {
287 Are63bitOperands(left_int, right_int)) {
288 const int64_t left_value = left_int.AsInt64Value(); 283 const int64_t left_value = left_int.AsInt64Value();
289 const int64_t right_value = right_int.AsInt64Value(); 284 if (Utils::IsInt(63, left_value)) {
290 switch (operation) { 285 const int64_t right_value = right_int.AsInt64Value();
291 case Token::kADD: 286 if (Utils::IsInt(63, right_value)) {
292 return Integer::New(left_value + right_value); 287 switch (operation) {
293 case Token::kSUB: 288 case Token::kADD:
294 return Integer::New(left_value - right_value); 289 return Integer::New(left_value + right_value);
295 case Token::kTRUNCDIV: 290 case Token::kSUB:
296 return Integer::New(left_value / right_value); 291 return Integer::New(left_value - right_value);
297 case Token::kMOD: { 292 case Token::kMUL: {
298 const int64_t remainder = left_value % right_value; 293 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) {
299 if (remainder < 0) { 294 return Integer::New(left_value * right_value);
300 if (right_value < 0) {
301 return Integer::New(remainder - right_value);
302 } else {
303 return Integer::New(remainder + right_value);
304 } 295 }
305 } else { 296 // Perform a Bigint multiplication below.
297 break;
298 }
299 case Token::kTRUNCDIV:
300 return Integer::New(left_value / right_value);
301 case Token::kMOD: {
302 const int64_t remainder = left_value % right_value;
303 if (remainder < 0) {
304 if (right_value < 0) {
305 return Integer::New(remainder - right_value);
306 } else {
307 return Integer::New(remainder + right_value);
308 }
309 }
306 return Integer::New(remainder); 310 return Integer::New(remainder);
307 } 311 }
312 default:
313 UNIMPLEMENTED();
314 }
308 } 315 }
309 default:
310 UNIMPLEMENTED();
311 } 316 }
312 UNREACHABLE();
313 return Integer::null();
314 } 317 }
315 const Bigint& left_big = Bigint::Handle(AsBigint(left_int)); 318 const Bigint& left_big = Bigint::Handle(AsBigint(left_int));
316 const Bigint& right_big = Bigint::Handle(AsBigint(right_int)); 319 const Bigint& right_big = Bigint::Handle(AsBigint(right_int));
317 const Bigint& result = 320 const Bigint& result =
318 Bigint::Handle(BinaryOpWithTwoBigints(operation, left_big, right_big)); 321 Bigint::Handle(BinaryOpWithTwoBigints(operation, left_big, right_big));
319 return Integer::Handle(AsInteger(result)).raw(); 322 return Integer::Handle(AsInteger(result)).raw();
320 } 323 }
321 324
322 325
323 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { 326 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) {
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 578
576 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { 579 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) {
577 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); 580 const Bigint& value = Bigint::CheckedHandle(arguments->At(0));
578 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); 581 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value));
579 ASSERT(CheckInteger(value)); 582 ASSERT(CheckInteger(value));
580 ASSERT(CheckInteger(result)); 583 ASSERT(CheckInteger(result));
581 arguments->SetReturn(Integer::Handle(AsInteger(result))); 584 arguments->SetReturn(Integer::Handle(AsInteger(result)));
582 } 585 }
583 586
584 } // namespace dart 587 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/platform/utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698