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

Side by Side Diff: runtime/vm/object.cc

Issue 747483002: Resubmit bigint changes of r41817 that were later reverted. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 1 month 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
« runtime/lib/bigint.dart ('K') | « runtime/vm/intrinsifier_x64.cc ('k') | no next file » | 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/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 16390 matching lines...) Expand 10 before | Expand all | Expand 10 after
16401 result.EnsureLength(2, space); 16401 result.EnsureLength(2, space);
16402 result.SetUsed(2); 16402 result.SetUsed(2);
16403 result.SetDigitAt(0, static_cast<uint32_t>(value)); 16403 result.SetDigitAt(0, static_cast<uint32_t>(value));
16404 result.SetDigitAt(1, static_cast<uint32_t>(value >> 32)); 16404 result.SetDigitAt(1, static_cast<uint32_t>(value >> 32));
16405 result.Clamp(); 16405 result.Clamp();
16406 return result.raw(); 16406 return result.raw();
16407 } 16407 }
16408 16408
16409 16409
16410 RawBigint* Bigint::NewFromShiftedInt64(int64_t value, intptr_t shift, 16410 RawBigint* Bigint::NewFromShiftedInt64(int64_t value, intptr_t shift,
16411 Heap::Space space) { 16411 Heap::Space space) {
16412 ASSERT(kBitsPerDigit == 32); 16412 ASSERT(kBitsPerDigit == 32);
16413 ASSERT(shift >= 0); 16413 ASSERT(shift >= 0);
16414 const Bigint& result = Bigint::Handle(New(space)); 16414 const Bigint& result = Bigint::Handle(New(space));
16415 const intptr_t digit_shift = shift / kBitsPerDigit; 16415 const intptr_t digit_shift = shift / kBitsPerDigit;
16416 const intptr_t bit_shift = shift % kBitsPerDigit; 16416 const intptr_t bit_shift = shift % kBitsPerDigit;
16417 result.EnsureLength(3 + digit_shift, space); 16417 result.EnsureLength(3 + digit_shift, space);
16418 result.SetUsed(3 + digit_shift); 16418 result.SetUsed(3 + digit_shift);
16419 uint64_t abs_value; 16419 uint64_t abs_value;
16420 if (value < 0) { 16420 if (value < 0) {
16421 result.SetNeg(true); 16421 result.SetNeg(true);
(...skipping 11 matching lines...) Expand all
16433 result.SetDigitAt(2 + digit_shift, 16433 result.SetDigitAt(2 + digit_shift,
16434 (bit_shift == 0) ? 0 16434 (bit_shift == 0) ? 0
16435 : static_cast<uint32_t>(abs_value >> (64 - bit_shift))); 16435 : static_cast<uint32_t>(abs_value >> (64 - bit_shift)));
16436 result.Clamp(); 16436 result.Clamp();
16437 return result.raw(); 16437 return result.raw();
16438 } 16438 }
16439 16439
16440 16440
16441 void Bigint::EnsureLength(intptr_t length, Heap::Space space) const { 16441 void Bigint::EnsureLength(intptr_t length, Heap::Space space) const {
16442 ASSERT(length >= 0); 16442 ASSERT(length >= 0);
16443 length++; // Account for leading zero for 64-bit processing.
16443 TypedData& old_digits = TypedData::Handle(digits()); 16444 TypedData& old_digits = TypedData::Handle(digits());
16444 if ((length > 0) && (length > old_digits.Length())) { 16445 if (length > old_digits.Length()) {
16445 TypedData& new_digits = TypedData::Handle( 16446 TypedData& new_digits = TypedData::Handle(
16446 TypedData::New(kTypedDataUint32ArrayCid, length + kExtraDigits, space)); 16447 TypedData::New(kTypedDataUint32ArrayCid, length + kExtraDigits, space));
16447 if (old_digits.Length() > 0) { 16448 set_digits(new_digits);
16449 if (Used() > 0) {
16448 TypedData::Copy(new_digits, TypedData::data_offset(), 16450 TypedData::Copy(new_digits, TypedData::data_offset(),
16449 old_digits, TypedData::data_offset(), 16451 old_digits, TypedData::data_offset(),
16450 old_digits.LengthInBytes()); 16452 (Used() + 1)*kBytesPerDigit); // Copy leading zero.
16451 } 16453 }
16452 set_digits(new_digits);
16453 } 16454 }
16454 } 16455 }
16455 16456
16456 16457
16457 void Bigint::Clamp() const { 16458 void Bigint::Clamp() const {
16458 intptr_t used = Used(); 16459 intptr_t used = Used();
16459 while ((used > 0) && (DigitAt(used - 1) == 0)) { 16460 if (used > 0) {
16460 --used; 16461 if (DigitAt(used - 1) == 0) {
16462 do {
16463 --used;
16464 } while ((used > 0) && (DigitAt(used - 1) == 0));
16465 SetUsed(used);
16466 }
16467 SetDigitAt(used, 0); // Set leading zero for 64-bit processing.
16461 } 16468 }
16462 SetUsed(used);
16463 } 16469 }
16464 16470
16465 16471
16466 bool Bigint::IsClamped() const { 16472 bool Bigint::IsClamped() const {
16467 intptr_t used = Used(); 16473 intptr_t used = Used();
16468 return (used == 0) || (DigitAt(used - 1) > 0); 16474 return (used == 0) || (DigitAt(used - 1) > 0);
16469 } 16475 }
16470 16476
16471 16477
16472 RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) { 16478 RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) {
16473 ASSERT(str != NULL); 16479 ASSERT(str != NULL);
16474 if (str[0] == '\0') {
16475 return NewFromInt64(0, space);
16476 }
16477
16478 // If the string starts with '-' recursively restart the whole operation 16480 // If the string starts with '-' recursively restart the whole operation
16479 // without the character and then toggle the sign. 16481 // without the character and then toggle the sign.
16480 // This allows multiple leading '-' (which will cancel each other out), but
16481 // we have added an assert, to make sure that the returned result of the
16482 // recursive call is not negative.
16483 // We don't catch leading '-'s for zero. Ex: "--0", or "---".
16484 if (str[0] == '-') { 16482 if (str[0] == '-') {
16483 ASSERT(str[1] != '-');
16485 const Bigint& result = Bigint::Handle(NewFromCString(&str[1], space)); 16484 const Bigint& result = Bigint::Handle(NewFromCString(&str[1], space));
16486 result.SetNeg(!result.Neg()); // Toggle sign. 16485 result.SetNeg(!result.Neg()); // Toggle sign.
16487 ASSERT(result.IsZero() || result.IsNegative()); 16486 ASSERT(result.IsZero() || result.IsNegative());
16488 ASSERT(result.IsClamped()); 16487 ASSERT(result.IsClamped());
16489 return result.raw(); 16488 return result.raw();
16490 } 16489 }
16491 16490
16492 // No overflow check needed since overflowing str_length implies that we take 16491 // No overflow check needed since overflowing str_length implies that we take
16493 // the branch to NewFromDecCString() which contains a check itself. 16492 // the branch to NewFromDecCString() which contains a check itself.
16494 const intptr_t str_length = strlen(str); 16493 const intptr_t str_length = strlen(str);
16495 if ((str_length > 2) && 16494 if ((str_length >= 2) &&
16496 (str[0] == '0') && 16495 (str[0] == '0') &&
16497 ((str[1] == 'x') || (str[1] == 'X'))) { 16496 ((str[1] == 'x') || (str[1] == 'X'))) {
16498 const Bigint& result = Bigint::Handle(NewFromHexCString(&str[2], space)); 16497 const Bigint& result = Bigint::Handle(NewFromHexCString(&str[2], space));
16499 ASSERT(result.IsClamped()); 16498 ASSERT(result.IsClamped());
16500 return result.raw(); 16499 return result.raw();
16501 } else { 16500 } else {
16502 return NewFromDecCString(str, space); 16501 return NewFromDecCString(str, space);
16503 } 16502 }
16504 } 16503 }
16505 16504
(...skipping 21 matching lines...) Expand all
16527 } 16526 }
16528 // The value needs to be added to the constants list. Grow the list if 16527 // The value needs to be added to the constants list. Grow the list if
16529 // it is full. 16528 // it is full.
16530 cls.InsertCanonicalConstant(index, value); 16529 cls.InsertCanonicalConstant(index, value);
16531 value.SetCanonical(); 16530 value.SetCanonical();
16532 return value.raw(); 16531 return value.raw();
16533 } 16532 }
16534 16533
16535 16534
16536 RawBigint* Bigint::NewFromHexCString(const char* str, Heap::Space space) { 16535 RawBigint* Bigint::NewFromHexCString(const char* str, Heap::Space space) {
16537 // TODO(regis): Do we need to check for max length?
16538 // If the string starts with '-' recursively restart the whole operation 16536 // If the string starts with '-' recursively restart the whole operation
16539 // without the character and then toggle the sign. 16537 // without the character and then toggle the sign.
16540 // This allows multiple leading '-' (which will cancel each other out), but
16541 // we have added an assert, to make sure that the returned result of the
16542 // recursive call is not negative.
16543 // We don't catch leading '-'s for zero. Ex: "--0", or "---".
16544 if (str[0] == '-') { 16538 if (str[0] == '-') {
16539 ASSERT(str[1] != '-');
16545 const Bigint& result = Bigint::Handle(NewFromHexCString(&str[1], space)); 16540 const Bigint& result = Bigint::Handle(NewFromHexCString(&str[1], space));
16546 result.SetNeg(!result.Neg()); // Toggle sign. 16541 if (!result.IsZero()) {
16547 ASSERT(result.IsZero() || result.IsNegative()); 16542 result.SetNeg(!result.Neg()); // Toggle sign.
16543 }
16548 ASSERT(result.IsClamped()); 16544 ASSERT(result.IsClamped());
16549 return result.raw(); 16545 return result.raw();
16550 } 16546 }
16551 const Bigint& result = Bigint::Handle(New(space)); 16547 const Bigint& result = Bigint::Handle(New(space));
16552 const int kBitsPerHexDigit = 4; 16548 const int kBitsPerHexDigit = 4;
16553 const int kHexDigitsPerDigit = 8; 16549 const int kHexDigitsPerDigit = 8;
16554 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit; 16550 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
16555 intptr_t hex_i = strlen(str); // Terminating byte excluded. 16551 intptr_t hex_i = strlen(str); // Terminating byte excluded.
16552 if ((hex_i <= 0) || (hex_i >= kMaxInt32)) {
16553 FATAL("Fatal error in Bigint::NewFromHexCString: string too long or empty");
16554 }
16556 result.EnsureLength((hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit, 16555 result.EnsureLength((hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit,
16557 space); 16556 space);
16558 intptr_t used_ = 0; 16557 intptr_t used_ = 0;
16559 uint32_t digit = 0; 16558 uint32_t digit = 0;
16560 intptr_t bit_i = 0; 16559 intptr_t bit_i = 0;
16561 while (--hex_i >= 0) { 16560 while (--hex_i >= 0) {
16562 digit += Utils::HexDigitToInt(str[hex_i]) << bit_i; 16561 digit += Utils::HexDigitToInt(str[hex_i]) << bit_i;
16563 bit_i += kBitsPerHexDigit; 16562 bit_i += kBitsPerHexDigit;
16564 if (bit_i == kBitsPerDigit) { 16563 if (bit_i == kBitsPerDigit) {
16565 bit_i = 0; 16564 bit_i = 0;
(...skipping 10 matching lines...) Expand all
16576 } 16575 }
16577 16576
16578 16577
16579 RawBigint* Bigint::NewFromDecCString(const char* str, Heap::Space space) { 16578 RawBigint* Bigint::NewFromDecCString(const char* str, Heap::Space space) {
16580 // Read 9 digits a time. 10^9 < 2^32. 16579 // Read 9 digits a time. 10^9 < 2^32.
16581 const int kDecDigitsPerIteration = 9; 16580 const int kDecDigitsPerIteration = 9;
16582 const uint32_t kTenMultiplier = 1000000000; 16581 const uint32_t kTenMultiplier = 1000000000;
16583 ASSERT(kBitsPerDigit == 32); 16582 ASSERT(kBitsPerDigit == 32);
16584 16583
16585 const intptr_t str_length = strlen(str); 16584 const intptr_t str_length = strlen(str);
16586 if (str_length < 0) { // TODO(regis): Pick a smaller limit. 16585 if ((str_length <= 0) || (str_length >= kMaxInt32)) {
16587 FATAL("Fatal error in Bigint::NewFromDecCString: string too long"); 16586 FATAL("Fatal error in Bigint::NewFromDecCString: string too long or empty");
16588 } 16587 }
16589 intptr_t str_pos = 0; 16588 intptr_t str_pos = 0;
16590 16589
16591 Bigint& result = Bigint::Handle(Bigint::New(space)); 16590 Bigint& result = Bigint::Handle(Bigint::New(space));
16592 // One decimal digit takes log2(10) bits, i.e. ~3.32192809489 bits. 16591 // One decimal digit takes log2(10) bits, i.e. ~3.32192809489 bits.
16593 // That is a theoretical limit for large numbers. 16592 // That is a theoretical limit for large numbers.
16594 // The extra digits allocated take care of variations (kExtraDigits). 16593 // The extra digits allocated take care of variations (kExtraDigits).
16595 const int64_t kLog10Dividend = 33219281; 16594 const int64_t kLog10Dividend = 33219281;
16596 const int64_t kLog10Divisor = 10000000; 16595 const int64_t kLog10Divisor = 10000000;
16596
16597 result.EnsureLength((kLog10Dividend * str_length) / 16597 result.EnsureLength((kLog10Dividend * str_length) /
16598 (kLog10Divisor * kBitsPerDigit) + 1, space); 16598 (kLog10Divisor * kBitsPerDigit) + 1, space);
16599 16599
16600 // Read first digit separately. This avoids a multiplication and addition. 16600 // Read first digit separately. This avoids a multiplication and addition.
16601 // The first digit might also not have kDecDigitsPerIteration decimal digits. 16601 // The first digit might also not have kDecDigitsPerIteration decimal digits.
16602 const intptr_t lsdigit_length = str_length % kDecDigitsPerIteration; 16602 const intptr_t lsdigit_length = str_length % kDecDigitsPerIteration;
16603 uint32_t digit = 0; 16603 uint32_t digit = 0;
16604 for (intptr_t i = 0; i < lsdigit_length; i++) { 16604 for (intptr_t i = 0; i < lsdigit_length; i++) {
16605 char c = str[str_pos++]; 16605 char c = str[str_pos++];
16606 ASSERT(('0' <= c) && (c <= '9')); 16606 ASSERT(('0' <= c) && (c <= '9'));
(...skipping 2539 matching lines...) Expand 10 before | Expand all | Expand 10 after
19146 return 0; 19146 return 0;
19147 } 19147 }
19148 // TODO(koda): Ensure VM classes only produce Smi hash codes, and remove 19148 // TODO(koda): Ensure VM classes only produce Smi hash codes, and remove
19149 // non-Smi cases once Dart-side implementation is complete. 19149 // non-Smi cases once Dart-side implementation is complete.
19150 Isolate* isolate = Isolate::Current(); 19150 Isolate* isolate = Isolate::Current();
19151 REUSABLE_INSTANCE_HANDLESCOPE(isolate); 19151 REUSABLE_INSTANCE_HANDLESCOPE(isolate);
19152 Instance& hash_code = isolate->InstanceHandle(); 19152 Instance& hash_code = isolate->InstanceHandle();
19153 hash_code ^= Instance::Cast(obj).HashCode(); 19153 hash_code ^= Instance::Cast(obj).HashCode();
19154 if (hash_code.IsSmi()) { 19154 if (hash_code.IsSmi()) {
19155 // May waste some bits on 64-bit, to ensure consistency with non-Smi case. 19155 // May waste some bits on 64-bit, to ensure consistency with non-Smi case.
19156 return static_cast<uword>(Smi::Cast(hash_code).Value() & 0xFFFFFFFF); 19156 return static_cast<uword>(Smi::Cast(hash_code).AsTruncatedUint32Value());
19157 // TODO(regis): Same as Smi::AsTruncatedUint32Value(), simplify?
19158 } else if (hash_code.IsInteger()) { 19157 } else if (hash_code.IsInteger()) {
19159 return static_cast<uword>( 19158 return static_cast<uword>(
19160 Integer::Cast(hash_code).AsTruncatedUint32Value()); 19159 Integer::Cast(hash_code).AsTruncatedUint32Value());
19161 } else { 19160 } else {
19162 return 0; 19161 return 0;
19163 } 19162 }
19164 } 19163 }
19165 }; 19164 };
19166 typedef EnumIndexHashMap<DefaultHashTraits> EnumIndexDefaultMap; 19165 typedef EnumIndexHashMap<DefaultHashTraits> EnumIndexDefaultMap;
19167 19166
(...skipping 1253 matching lines...) Expand 10 before | Expand all | Expand 10 after
20421 return tag_label.ToCString(); 20420 return tag_label.ToCString();
20422 } 20421 }
20423 20422
20424 20423
20425 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 20424 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
20426 Instance::PrintJSONImpl(stream, ref); 20425 Instance::PrintJSONImpl(stream, ref);
20427 } 20426 }
20428 20427
20429 20428
20430 } // namespace dart 20429 } // namespace dart
OLDNEW
« runtime/lib/bigint.dart ('K') | « runtime/vm/intrinsifier_x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698