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

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

Issue 9114054: Port a couple more stubs to x64. (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
OLDNEW
1 // Copyright (c) 2011, 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"
11 #include "vm/object.h" 11 #include "vm/object.h"
(...skipping 49 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
71 static RawInteger* IntegerBitOperation(Token::Kind kind, 85 static RawInteger* IntegerBitOperation(Token::Kind kind,
72 const Integer& op1_int, 86 const Integer& op1_int,
73 const Integer& op2_int) { 87 const Integer& op2_int) {
74 if (op1_int.IsSmi() && op2_int.IsSmi()) { 88 if (op1_int.IsSmi() && op2_int.IsSmi()) {
75 Smi& op1 = Smi::Handle(); 89 Smi& op1 = Smi::Handle();
76 Smi& op2 = Smi::Handle(); 90 Smi& op2 = Smi::Handle();
77 op1 ^= op1_int.raw(); 91 op1 ^= op1_int.raw();
78 op2 ^= op2_int.raw(); 92 op2 ^= op2_int.raw();
79 intptr_t result = 0; 93 intptr_t result = 0;
80 switch (kind) { 94 switch (kind) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 left.ToCString(), right.ToCString()); 211 left.ToCString(), right.ToCString());
198 } 212 }
199 Integer& result = Integer::Handle( 213 Integer& result = Integer::Handle(
200 IntegerBitOperation(Token::kBIT_XOR, left, right)); 214 IntegerBitOperation(Token::kBIT_XOR, left, right));
201 arguments->SetReturn(Integer::Handle(AsInteger(result))); 215 arguments->SetReturn(Integer::Handle(AsInteger(result)));
202 } 216 }
203 217
204 218
205 // The result is invalid if it is outside the range 219 // The result is invalid if it is outside the range
206 // Smi::kMinValue..Smi::kMaxValue. 220 // Smi::kMinValue..Smi::kMaxValue.
221 // Note that the 64-bit result of adding or subtracting 63-bit signed values
222 // cannot overflow.
207 static int64_t BinaryOpWithTwoSmis(Token::Kind operation, 223 static int64_t BinaryOpWithTwoSmis(Token::Kind operation,
208 const Smi& left, 224 const Smi& left,
209 const Smi& right) { 225 const Smi& right) {
210 switch (operation) { 226 switch (operation) {
211 case Token::kADD: 227 case Token::kADD:
212 // TODO(regis): We may need an overflow check in 64-bit mode. Revisit.
213 return left.Value() + right.Value(); 228 return left.Value() + right.Value();
214 case Token::kSUB: 229 case Token::kSUB:
215 return left.Value() - right.Value(); 230 return left.Value() - right.Value();
216 case Token::kMUL: { 231 case Token::kMUL: {
217 // TODO(regis): Using Bigint here may be a performance issue. Revisit. 232 ASSERT(Smi::kBits < 32); // Do not use this code in 64-bit mode.
Ivan Posva 2012/01/13 06:27:40 I am a bit concerned how this logic is split up be
regis 2012/01/13 18:57:31 I have merged this helper into its caller, which m
218 const Bigint& big_left = 233 int64_t result_64 =
219 Bigint::Handle(BigintOperations::NewFromSmi(left)); 234 static_cast<int64_t>(left.Value()) *
220 const Bigint& big_right = 235 static_cast<int64_t>(right.Value());
221 Bigint::Handle(BigintOperations::NewFromSmi(right)); 236 return result_64;
222 const Bigint& big_result =
223 Bigint::Handle(BigintOperations::Multiply(big_left, big_right));
224 if (BigintOperations::FitsIntoInt64(big_result)) {
225 return BigintOperations::ToInt64(big_result);
226 } else {
227 // Overflow, return an invalid Smi.
228 return Smi::kMaxValue + 1;
229 }
230 } 237 }
231 case Token::kTRUNCDIV: 238 case Token::kTRUNCDIV:
232 return left.Value() / right.Value(); 239 return left.Value() / right.Value();
233 case Token::kMOD: { 240 case Token::kMOD: {
234 intptr_t remainder = left.Value() % right.Value(); 241 intptr_t remainder = left.Value() % right.Value();
235 if (remainder < 0) { 242 if (remainder < 0) {
236 if (right.Value() < 0) { 243 if (right.Value() < 0) {
237 return remainder - right.Value(); 244 return remainder - right.Value();
238 } else { 245 } else {
239 return remainder + right.Value(); 246 return remainder + right.Value();
(...skipping 23 matching lines...) Expand all
263 return BigintOperations::Divide(left, right); 270 return BigintOperations::Divide(left, right);
264 case Token::kMOD: 271 case Token::kMOD:
265 return BigintOperations::Modulo(left, right); 272 return BigintOperations::Modulo(left, right);
266 default: 273 default:
267 UNIMPLEMENTED(); 274 UNIMPLEMENTED();
268 return Bigint::null(); 275 return Bigint::null();
269 } 276 }
270 } 277 }
271 278
272 279
273 // TODO(srdjan): Implement correct overflow checking before allowing 64 bit
274 // operands.
275 static bool AreBoth64bitOperands(const Integer& op1, const Integer& op2) {
276 return false;
277 }
278
279
280 static RawInteger* IntegerBinopHelper(Token::Kind operation, 280 static RawInteger* IntegerBinopHelper(Token::Kind operation,
281 const Integer& left_int, 281 const Integer& left_int,
282 const Integer& right_int) { 282 const Integer& right_int) {
283 if (left_int.IsSmi() && right_int.IsSmi()) { 283 // The result of any operation (except multiplication in 64-bit mode) between
284 // two Smi will always fit in a 64-bit signed result (no overflow).
285 if (((Smi::kBits < 32) || (operation != Token::kMUL)) &&
286 left_int.IsSmi() && right_int.IsSmi()) {
284 Smi& left_smi = Smi::Handle(); 287 Smi& left_smi = Smi::Handle();
285 Smi& right_smi = Smi::Handle(); 288 Smi& right_smi = Smi::Handle();
286 left_smi ^= left_int.raw(); 289 left_smi ^= left_int.raw();
287 right_smi ^= right_int.raw(); 290 right_smi ^= right_int.raw();
288 int64_t result = BinaryOpWithTwoSmis(operation, left_smi, right_smi); 291 int64_t result = BinaryOpWithTwoSmis(operation, left_smi, right_smi);
289 if (Smi::IsValid64(result)) { 292 return Integer::New(result);
290 return Smi::New(result); 293
291 } else { 294 } else if ((operation != Token::kMUL) &&
292 // TODO(regis): This is not going to work on x64. Check other operations. 295 Are63bitOperands(left_int, right_int)) {
293 #if defined(TARGET_ARCH_X64) 296 // The result of any operation (except multiplication) between two 63-bit
294 UNIMPLEMENTED(); 297 // signed integers will fit in a 64-bit signed result.
295 return 0;
296 #else
297 // Overflow to Mint.
298 return Mint::New(result);
299 #endif
300 }
301 } else if (AreBoth64bitOperands(left_int, right_int)) {
302 // TODO(srdjan): Test for overflow of result instead of operand
303 // types.
304 const int64_t a = left_int.AsInt64Value(); 298 const int64_t a = left_int.AsInt64Value();
305 const int64_t b = right_int.AsInt64Value(); 299 const int64_t b = right_int.AsInt64Value();
306 switch (operation) { 300 switch (operation) {
307 case Token::kADD: 301 case Token::kADD:
308 return Integer::New(a + b); 302 return Integer::New(a + b);
309 case Token::kSUB: 303 case Token::kSUB:
310 return Integer::New(a - b); 304 return Integer::New(a - b);
311 case Token::kMUL:
312 return Integer::New(a * b);
313 case Token::kTRUNCDIV: 305 case Token::kTRUNCDIV:
314 return Integer::New(a / b); 306 return Integer::New(a / b);
315 case Token::kMOD: { 307 case Token::kMOD: {
316 int64_t remainder = a % b; 308 int64_t remainder = a % b;
317 int64_t c = 0; 309 int64_t c = 0;
318 if (remainder < 0) { 310 if (remainder < 0) {
319 if (b < 0) { 311 if (b < 0) {
320 c = remainder - b; 312 c = remainder - b;
321 } else { 313 } else {
322 c = remainder + b; 314 c = remainder + b;
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 } 444 }
453 445
454 446
455 // TODO(srdjan): Clarify handling of negative right operand in a shift op. 447 // TODO(srdjan): Clarify handling of negative right operand in a shift op.
456 static RawInteger* SmiShiftOperation(Token::Kind kind, 448 static RawInteger* SmiShiftOperation(Token::Kind kind,
457 const Smi& left, 449 const Smi& left,
458 const Smi& right) { 450 const Smi& right) {
459 ASSERT(right.Value() >= 0); 451 ASSERT(right.Value() >= 0);
460 intptr_t result = 0; 452 intptr_t result = 0;
461 switch (kind) { 453 switch (kind) {
462 case Token::kSHL: 454 case Token::kSHL: {
463 if ((left.Value() == 0) || (right.Value() == 0)) { 455 if ((left.Value() == 0) || (right.Value() == 0)) {
464 return left.raw(); 456 return left.raw();
465 } 457 }
466 { // Check for overflow. 458 { // Check for overflow.
467 int cnt = HighestBit(left.Value()); 459 int cnt = HighestBit(left.Value());
468 if ((cnt + right.Value()) >= Smi::kBits) { 460 if ((cnt + right.Value()) >= Smi::kBits) {
469 if ((cnt + right.Value()) >= Mint::kBits) { 461 if ((cnt + right.Value()) >= Mint::kBits) {
470 return BigintOperations::ShiftLeft( 462 return BigintOperations::ShiftLeft(
471 Bigint::Handle(AsBigint(left)), right.Value()); 463 Bigint::Handle(AsBigint(left)), right.Value());
472 } else { 464 } else {
473 int64_t left_64 = left.Value(); 465 int64_t left_64 = left.Value();
474 return Integer::New(left_64 << right.Value()); 466 return Integer::New(left_64 << right.Value());
475 } 467 }
476 } 468 }
477 } 469 }
478 result = left.Value() << right.Value(); 470 result = left.Value() << right.Value();
479 break; 471 break;
472 }
480 case Token::kSAR: { 473 case Token::kSAR: {
481 int shift_amount = (right.Value() > 0x1F) ? 0x1F : right.Value(); 474 const int shift_amount =
482 result = left.Value() >> shift_amount; 475 (right.Value() >= kBitsPerWord) ? (kBitsPerWord - 1) : right.Value();
483 break; 476 result = left.Value() >> shift_amount;
484 } 477 break;
478 }
485 default: 479 default:
486 UNIMPLEMENTED(); 480 UNIMPLEMENTED();
487 } 481 }
488 ASSERT(Smi::IsValid(result)); 482 ASSERT(Smi::IsValid(result));
489 return Smi::New(result); 483 return Smi::New(result);
490 } 484 }
491 485
492 486
493 static RawInteger* ShiftOperationHelper(Token::Kind kind, 487 static RawInteger* ShiftOperationHelper(Token::Kind kind,
494 const Integer& value, 488 const Integer& value,
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 583
590 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { 584 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) {
591 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); 585 const Bigint& value = Bigint::CheckedHandle(arguments->At(0));
592 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); 586 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value));
593 ASSERT(CheckInteger(value)); 587 ASSERT(CheckInteger(value));
594 ASSERT(CheckInteger(result)); 588 ASSERT(CheckInteger(result));
595 arguments->SetReturn(Integer::Handle(AsInteger(result))); 589 arguments->SetReturn(Integer::Handle(AsInteger(result)));
596 } 590 }
597 591
598 } // namespace dart 592 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/lib/date.cc ('k') | runtime/lib/integers.dart » ('j') | runtime/vm/cpu_x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698