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

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

Issue 842033005: Make Bigint instances immutable by removing all setters. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 10 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
« runtime/lib/bigint.dart ('K') | « runtime/vm/object.h ('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 16343 matching lines...) Expand 10 before | Expand all | Expand 10 after
16354 // "Double". Return "double" instead. 16354 // "Double". Return "double" instead.
16355 AddTypeProperties(&jsobj, "double", "double", ref); 16355 AddTypeProperties(&jsobj, "double", "double", ref);
16356 PrintSharedInstanceJSON(&jsobj, ref); 16356 PrintSharedInstanceJSON(&jsobj, ref);
16357 ObjectIdRing* ring = Isolate::Current()->object_id_ring(); 16357 ObjectIdRing* ring = Isolate::Current()->object_id_ring();
16358 const intptr_t id = ring->GetIdForObject(raw()); 16358 const intptr_t id = ring->GetIdForObject(raw());
16359 jsobj.AddPropertyF("id", "objects/%" Pd "", id); 16359 jsobj.AddPropertyF("id", "objects/%" Pd "", id);
16360 jsobj.AddProperty("valueAsString", ToCString()); 16360 jsobj.AddProperty("valueAsString", ToCString());
16361 } 16361 }
16362 16362
16363 16363
16364 void Bigint::set_neg(const Bool& value) const {
16365 StorePointer(&raw_ptr()->neg_, value.raw());
16366 }
16367
16368
16369 void Bigint::set_used(const Smi& value) const {
16370 StoreSmi(&raw_ptr()->used_, value.raw());
16371 }
16372
16373
16374 void Bigint::set_digits(const TypedData& value) const {
16375 // The VM expects digits_ to be a Uint32List (not null).
16376 ASSERT(!value.IsNull() && (value.GetClassId() == kTypedDataUint32ArrayCid));
16377 StorePointer(&raw_ptr()->digits_, value.raw());
16378 }
16379
16380
16381 bool Bigint::Neg() const { 16364 bool Bigint::Neg() const {
16382 return Bool::Handle(neg()).value(); 16365 return Bool::Handle(neg()).value();
16383 } 16366 }
16384 16367
16385 16368
16386 void Bigint::SetNeg(bool value) const { 16369 void Bigint::SetNeg(bool value) const {
16387 set_neg(Bool::Get(value)); 16370 StorePointer(&raw_ptr()->neg_, Bool::Get(value).raw());
16388 } 16371 }
16389 16372
16390 16373
16391 intptr_t Bigint::Used() const { 16374 intptr_t Bigint::Used() const {
16392 return Smi::Value(used()); 16375 return Smi::Value(used());
16393 } 16376 }
16394 16377
16395 16378
16396 void Bigint::SetUsed(intptr_t value) const { 16379 void Bigint::SetUsed(intptr_t value) const {
16397 set_used(Smi::Handle(Smi::New(value))); 16380 StoreSmi(&raw_ptr()->used_, Smi::New(value));
16398 } 16381 }
16399 16382
16400 16383
16401 uint32_t Bigint::DigitAt(intptr_t index) const { 16384 uint32_t Bigint::DigitAt(intptr_t index) const {
16402 const TypedData& typed_data = TypedData::Handle(digits()); 16385 const TypedData& typed_data = TypedData::Handle(digits());
16403 return typed_data.GetUint32(index << 2); 16386 return typed_data.GetUint32(index << 2);
16404 } 16387 }
16405 16388
16406 16389
16407 void Bigint::SetDigitAt(intptr_t index, uint32_t value) const { 16390 void Bigint::set_digits(const TypedData& value) const {
16408 const TypedData& typed_data = TypedData::Handle(digits()); 16391 // The VM expects digits_ to be a Uint32List (not null).
16409 typed_data.SetUint32(index << 2, value); 16392 ASSERT(!value.IsNull() && (value.GetClassId() == kTypedDataUint32ArrayCid));
16393 StorePointer(&raw_ptr()->digits_, value.raw());
16394 }
16395
16396
16397 RawTypedData* Bigint::NewDigits(intptr_t length, Heap::Space space) {
16398 ASSERT(length > 0);
16399 // Account for leading zero for 64-bit processing.
16400 return TypedData::New(kTypedDataUint32ArrayCid, length + 1, space);
16401 }
16402
16403
16404 uint32_t Bigint::DigitAt(const TypedData& digits, intptr_t index) {
16405 return digits.GetUint32(index << 2);
16406 }
16407
16408
16409 void Bigint::SetDigitAt(const TypedData& digits,
16410 intptr_t index,
16411 uint32_t value) {
16412 digits.SetUint32(index << 2, value);
16410 } 16413 }
16411 16414
16412 16415
16413 bool Bigint::Equals(const Instance& other) const { 16416 bool Bigint::Equals(const Instance& other) const {
16414 if (this->raw() == other.raw()) { 16417 if (this->raw() == other.raw()) {
16415 // Both handles point to the same raw instance. 16418 // Both handles point to the same raw instance.
16416 return true; 16419 return true;
16417 } 16420 }
16418 16421
16419 if (!other.IsBigint() || other.IsNull()) { 16422 if (!other.IsBigint() || other.IsNull()) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
16461 Isolate* isolate = Isolate::Current(); 16464 Isolate* isolate = Isolate::Current();
16462 ASSERT(isolate->object_store()->bigint_class() != Class::null()); 16465 ASSERT(isolate->object_store()->bigint_class() != Class::null());
16463 Bigint& result = Bigint::Handle(isolate); 16466 Bigint& result = Bigint::Handle(isolate);
16464 { 16467 {
16465 RawObject* raw = Object::Allocate(Bigint::kClassId, 16468 RawObject* raw = Object::Allocate(Bigint::kClassId,
16466 Bigint::InstanceSize(), 16469 Bigint::InstanceSize(),
16467 space); 16470 space);
16468 NoGCScope no_gc; 16471 NoGCScope no_gc;
16469 result ^= raw; 16472 result ^= raw;
16470 } 16473 }
16471 result.set_neg(Bool::Get(false)); 16474 result.SetNeg(false);
16472 result.set_used(Smi::Handle(isolate, Smi::New(0))); 16475 result.SetUsed(0);
16473 result.set_digits( 16476 result.set_digits(
16474 TypedData::Handle(isolate, TypedData::EmptyUint32Array(isolate))); 16477 TypedData::Handle(isolate, TypedData::EmptyUint32Array(isolate)));
16475 return result.raw(); 16478 return result.raw();
16476 } 16479 }
16477 16480
16478 16481
16482 RawBigint* Bigint::New(bool neg, intptr_t used, const TypedData& digits,
16483 Heap::Space space) {
16484 ASSERT((used == 0) ||
16485 (!digits.IsNull() && (digits.Length() >= (used + (used & 1)))));
16486 Isolate* isolate = Isolate::Current();
16487 ASSERT(isolate->object_store()->bigint_class() != Class::null());
16488 Bigint& result = Bigint::Handle(isolate);
16489 {
16490 RawObject* raw = Object::Allocate(Bigint::kClassId,
16491 Bigint::InstanceSize(),
16492 space);
16493 NoGCScope no_gc;
16494 result ^= raw;
16495 }
16496 // Clamp the digits array.
16497 while ((used > 0) && (digits.GetUint32((used - 1) << 2) == 0)) {
16498 --used;
16499 }
16500 if (used > 0) {
16501 if ((used & 1) != 0) {
16502 // Set leading zero for 64-bit processing of digit pairs.
16503 digits.SetUint32(used << 2, 0);
16504 }
16505 result.set_digits(digits);
16506 } else {
16507 neg = false;
16508 result.set_digits(
16509 TypedData::Handle(isolate, TypedData::EmptyUint32Array(isolate)));
16510 }
16511 result.SetNeg(neg);
16512 result.SetUsed(used);
16513 return result.raw();
16514 }
16515
16516
16479 RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) { 16517 RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) {
16480 const Bigint& result = Bigint::Handle(New(space)); 16518 const TypedData& digits = TypedData::Handle(NewDigits(2, space));
16481 result.EnsureLength(2, space); 16519 bool neg;
16482 result.SetUsed(2); 16520 uint64_t abs_value;
16483 if (value < 0) { 16521 if (value < 0) {
16484 result.SetNeg(true); 16522 neg = true;
16485 value = -value; // No concern about overflow, since sign is captured. 16523 abs_value = -value;
16524 } else {
16525 neg = false;
16526 abs_value = value;
16486 } 16527 }
16487 result.SetDigitAt(0, static_cast<uint32_t>(value)); 16528 SetDigitAt(digits, 0, static_cast<uint32_t>(abs_value));
16488 result.SetDigitAt(1, static_cast<uint32_t>(value >> 32)); // value >= 0. 16529 SetDigitAt(digits, 1, static_cast<uint32_t>(abs_value >> 32));
16489 result.Clamp(); 16530 return New(neg, 2, digits, space);
16490 return result.raw();
16491 } 16531 }
16492 16532
16493 16533
16494 RawBigint* Bigint::NewFromUint64(uint64_t value, Heap::Space space) { 16534 RawBigint* Bigint::NewFromUint64(uint64_t value, Heap::Space space) {
16495 const Bigint& result = Bigint::Handle(New(space)); 16535 const TypedData& digits = TypedData::Handle(NewDigits(2, space));
16496 result.EnsureLength(2, space); 16536 SetDigitAt(digits, 0, static_cast<uint32_t>(value));
16497 result.SetUsed(2); 16537 SetDigitAt(digits, 1, static_cast<uint32_t>(value >> 32));
16498 result.SetDigitAt(0, static_cast<uint32_t>(value)); 16538 return New(false, 2, digits, space);
16499 result.SetDigitAt(1, static_cast<uint32_t>(value >> 32));
16500 result.Clamp();
16501 return result.raw();
16502 } 16539 }
16503 16540
16504 16541
16505 RawBigint* Bigint::NewFromShiftedInt64(int64_t value, intptr_t shift, 16542 RawBigint* Bigint::NewFromShiftedInt64(int64_t value, intptr_t shift,
16506 Heap::Space space) { 16543 Heap::Space space) {
16507 ASSERT(kBitsPerDigit == 32); 16544 ASSERT(kBitsPerDigit == 32);
16508 ASSERT(shift >= 0); 16545 ASSERT(shift >= 0);
16509 const Bigint& result = Bigint::Handle(New(space));
16510 const intptr_t digit_shift = shift / kBitsPerDigit; 16546 const intptr_t digit_shift = shift / kBitsPerDigit;
16511 const intptr_t bit_shift = shift % kBitsPerDigit; 16547 const intptr_t bit_shift = shift % kBitsPerDigit;
16512 result.EnsureLength(3 + digit_shift, space); 16548 const intptr_t used = 3 + digit_shift;
16513 result.SetUsed(3 + digit_shift); 16549 const TypedData& digits = TypedData::Handle(NewDigits(used, space));
16550 bool neg;
16514 uint64_t abs_value; 16551 uint64_t abs_value;
16515 if (value < 0) { 16552 if (value < 0) {
16516 result.SetNeg(true); 16553 neg = true;
16517 abs_value = -value; // No concern about overflow, since sign is captured. 16554 abs_value = -value;
16518 } else { 16555 } else {
16556 neg = false;
16519 abs_value = value; 16557 abs_value = value;
16520 } 16558 }
16521 for (intptr_t i = 0; i < digit_shift; i++) { 16559 for (intptr_t i = 0; i < digit_shift; i++) {
16522 result.SetDigitAt(i, 0); 16560 SetDigitAt(digits, i, 0);
16523 } 16561 }
16524 result.SetDigitAt(0 + digit_shift, 16562 SetDigitAt(digits, 0 + digit_shift,
16525 static_cast<uint32_t>(abs_value << bit_shift)); 16563 static_cast<uint32_t>(abs_value << bit_shift));
16526 result.SetDigitAt(1 + digit_shift, 16564 SetDigitAt(digits, 1 + digit_shift,
16527 static_cast<uint32_t>(abs_value >> (32 - bit_shift))); 16565 static_cast<uint32_t>(abs_value >> (32 - bit_shift)));
16528 result.SetDigitAt(2 + digit_shift, 16566 SetDigitAt(digits, 2 + digit_shift,
16529 (bit_shift == 0) ? 0 16567 (bit_shift == 0) ? 0
16530 : static_cast<uint32_t>(abs_value >> (64 - bit_shift))); 16568 : static_cast<uint32_t>(abs_value >> (64 - bit_shift)));
16531 result.Clamp(); 16569 return New(neg, used, digits, space);
16532 return result.raw();
16533 }
16534
16535
16536 void Bigint::EnsureLength(intptr_t length, Heap::Space space) const {
16537 ASSERT(length >= 0);
16538 length++; // Account for leading zero for 64-bit processing.
16539 TypedData& old_digits = TypedData::Handle(digits());
16540 if (length > old_digits.Length()) {
16541 TypedData& new_digits = TypedData::Handle(
16542 TypedData::New(kTypedDataUint32ArrayCid, length + kExtraDigits, space));
16543 set_digits(new_digits);
16544 if (Used() > 0) {
16545 TypedData::Copy(new_digits, TypedData::data_offset(),
16546 old_digits, TypedData::data_offset(),
16547 (Used() + 1)*kBytesPerDigit); // Copy leading zero.
16548 }
16549 }
16550 }
16551
16552
16553 void Bigint::Clamp() const {
16554 intptr_t used = Used();
16555 if (used > 0) {
16556 if (DigitAt(used - 1) == 0) {
16557 do {
16558 --used;
16559 } while ((used > 0) && (DigitAt(used - 1) == 0));
16560 SetUsed(used);
16561 }
16562 SetDigitAt(used, 0); // Set leading zero for 64-bit processing.
16563 }
16564 }
16565
16566
16567 bool Bigint::IsClamped() const {
16568 intptr_t used = Used();
16569 return (used == 0) || (DigitAt(used - 1) > 0);
16570 } 16570 }
16571 16571
16572 16572
16573 RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) { 16573 RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) {
16574 ASSERT(str != NULL); 16574 ASSERT(str != NULL);
16575 // If the string starts with '-' recursively restart the whole operation 16575 bool neg = false;
16576 // without the character and then toggle the sign. 16576 TypedData& digits = TypedData::Handle();
16577 if (str[0] == '-') { 16577 if (str[0] == '-') {
16578 ASSERT(str[1] != '-'); 16578 ASSERT(str[1] != '-');
16579 const Bigint& result = Bigint::Handle(NewFromCString(&str[1], space)); 16579 neg = true;
16580 result.SetNeg(!result.Neg()); // Toggle sign. 16580 str++;
16581 ASSERT(result.IsZero() || result.IsNegative());
16582 ASSERT(result.IsClamped());
16583 return result.raw();
16584 } 16581 }
16585 16582 intptr_t used;
16586 // No overflow check needed since overflowing str_length implies that we take
16587 // the branch to NewFromDecCString() which contains a check itself.
16588 const intptr_t str_length = strlen(str); 16583 const intptr_t str_length = strlen(str);
16589 if ((str_length >= 2) && 16584 if ((str_length >= 2) &&
16590 (str[0] == '0') && 16585 (str[0] == '0') &&
16591 ((str[1] == 'x') || (str[1] == 'X'))) { 16586 ((str[1] == 'x') || (str[1] == 'X'))) {
16592 const Bigint& result = Bigint::Handle(NewFromHexCString(&str[2], space)); 16587 digits = NewDigitsFromHexCString(&str[2], &used, space);
16593 ASSERT(result.IsClamped());
16594 return result.raw();
16595 } else { 16588 } else {
16596 return NewFromDecCString(str, space); 16589 digits = NewDigitsFromDecCString(str, &used, space);
16597 } 16590 }
16591 return New(neg, used, digits, space);
16598 } 16592 }
16599 16593
16600 16594
16601 RawBigint* Bigint::NewCanonical(const String& str) { 16595 RawBigint* Bigint::NewCanonical(const String& str) {
16602 const Bigint& value = Bigint::Handle( 16596 const Bigint& value = Bigint::Handle(
16603 Bigint::NewFromCString(str.ToCString(), Heap::kOld)); 16597 Bigint::NewFromCString(str.ToCString(), Heap::kOld));
16604 const Class& cls = 16598 const Class& cls =
16605 Class::Handle(Isolate::Current()->object_store()->bigint_class()); 16599 Class::Handle(Isolate::Current()->object_store()->bigint_class());
16606 const Array& constants = Array::Handle(cls.constants()); 16600 const Array& constants = Array::Handle(cls.constants());
16607 const intptr_t constants_len = constants.Length(); 16601 const intptr_t constants_len = constants.Length();
(...skipping 12 matching lines...) Expand all
16620 index++; 16614 index++;
16621 } 16615 }
16622 // The value needs to be added to the constants list. Grow the list if 16616 // The value needs to be added to the constants list. Grow the list if
16623 // it is full. 16617 // it is full.
16624 cls.InsertCanonicalConstant(index, value); 16618 cls.InsertCanonicalConstant(index, value);
16625 value.SetCanonical(); 16619 value.SetCanonical();
16626 return value.raw(); 16620 return value.raw();
16627 } 16621 }
16628 16622
16629 16623
16630 RawBigint* Bigint::NewFromHexCString(const char* str, Heap::Space space) { 16624 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used,
16631 // If the string starts with '-' recursively restart the whole operation 16625 Heap::Space space) {
16632 // without the character and then toggle the sign.
16633 if (str[0] == '-') {
16634 ASSERT(str[1] != '-');
16635 const Bigint& result = Bigint::Handle(NewFromHexCString(&str[1], space));
16636 if (!result.IsZero()) {
16637 result.SetNeg(!result.Neg()); // Toggle sign.
16638 }
16639 ASSERT(result.IsClamped());
16640 return result.raw();
16641 }
16642 const Bigint& result = Bigint::Handle(New(space));
16643 const int kBitsPerHexDigit = 4; 16626 const int kBitsPerHexDigit = 4;
16644 const int kHexDigitsPerDigit = 8; 16627 const int kHexDigitsPerDigit = 8;
16645 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit; 16628 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
16646 intptr_t hex_i = strlen(str); // Terminating byte excluded. 16629 intptr_t hex_i = strlen(str); // Terminating byte excluded.
16647 if ((hex_i <= 0) || (hex_i >= kMaxInt32)) { 16630 if ((hex_i <= 0) || (hex_i >= kMaxInt32)) {
16648 FATAL("Fatal error in Bigint::NewFromHexCString: string too long or empty"); 16631 FATAL("Fatal error parsing hex bigint: string too long or empty");
16649 } 16632 }
16650 result.EnsureLength((hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit, 16633 const intptr_t length = (hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit;
16651 space); 16634 const TypedData& digits = TypedData::Handle(NewDigits(length, space));
16652 intptr_t used_ = 0; 16635 intptr_t used_ = 0;
16653 uint32_t digit = 0; 16636 uint32_t digit = 0;
16654 intptr_t bit_i = 0; 16637 intptr_t bit_i = 0;
16655 while (--hex_i >= 0) { 16638 while (--hex_i >= 0) {
16656 digit += Utils::HexDigitToInt(str[hex_i]) << bit_i; 16639 digit += Utils::HexDigitToInt(str[hex_i]) << bit_i;
16657 bit_i += kBitsPerHexDigit; 16640 bit_i += kBitsPerHexDigit;
16658 if (bit_i == kBitsPerDigit) { 16641 if (bit_i == kBitsPerDigit) {
16659 bit_i = 0; 16642 bit_i = 0;
16660 result.SetDigitAt(used_++, digit); 16643 SetDigitAt(digits, used_++, digit);
16661 digit = 0; 16644 digit = 0;
16662 } 16645 }
16663 } 16646 }
16664 if (bit_i != 0) { 16647 if (bit_i != 0) {
16665 result.SetDigitAt(used_++, digit); 16648 SetDigitAt(digits, used_++, digit);
16666 } 16649 }
16667 result.SetUsed(used_); 16650 *used = used_;
16668 result.Clamp(); 16651 return digits.raw();
16669 return result.raw();
16670 } 16652 }
16671 16653
16672 16654
16673 RawBigint* Bigint::NewFromDecCString(const char* str, Heap::Space space) { 16655 RawTypedData* Bigint::NewDigitsFromDecCString(const char* str, intptr_t* used,
16656 Heap::Space space) {
16674 // Read 9 digits a time. 10^9 < 2^32. 16657 // Read 9 digits a time. 10^9 < 2^32.
16675 const int kDecDigitsPerIteration = 9; 16658 const int kDecDigitsPerIteration = 9;
16676 const uint32_t kTenMultiplier = 1000000000; 16659 const uint32_t kTenMultiplier = 1000000000;
16677 ASSERT(kBitsPerDigit == 32); 16660 ASSERT(kBitsPerDigit == 32);
16678
16679 const intptr_t str_length = strlen(str); 16661 const intptr_t str_length = strlen(str);
16680 if ((str_length <= 0) || (str_length >= kMaxInt32)) { 16662 if ((str_length <= 0) || (str_length >= kMaxInt32)) {
16681 FATAL("Fatal error in Bigint::NewFromDecCString: string too long or empty"); 16663 FATAL("Fatal error parsing dec bigint: string too long or empty");
16682 } 16664 }
16683 intptr_t str_pos = 0;
16684
16685 Bigint& result = Bigint::Handle(Bigint::New(space));
16686 // One decimal digit takes log2(10) bits, i.e. ~3.32192809489 bits. 16665 // One decimal digit takes log2(10) bits, i.e. ~3.32192809489 bits.
16687 // That is a theoretical limit for large numbers. 16666 // That is a theoretical limit for large numbers.
16688 // The extra digits allocated take care of variations (kExtraDigits). 16667 // The extra 5 digits allocated take care of variations.
16689 const int64_t kLog10Dividend = 33219281; 16668 const int64_t kLog10Dividend = 33219281;
16690 const int64_t kLog10Divisor = 10000000; 16669 const int64_t kLog10Divisor = 10000000;
16691 16670 const intptr_t length = (kLog10Dividend * str_length) /
16692 result.EnsureLength((kLog10Dividend * str_length) / 16671 (kLog10Divisor * kBitsPerDigit) + 5;
16693 (kLog10Divisor * kBitsPerDigit) + 1, space); 16672 const TypedData& digits = TypedData::Handle(NewDigits(length, space));
16694
16695 // Read first digit separately. This avoids a multiplication and addition. 16673 // Read first digit separately. This avoids a multiplication and addition.
16696 // The first digit might also not have kDecDigitsPerIteration decimal digits. 16674 // The first digit might also not have kDecDigitsPerIteration decimal digits.
16697 const intptr_t lsdigit_length = str_length % kDecDigitsPerIteration; 16675 const intptr_t lsdigit_length = str_length % kDecDigitsPerIteration;
16698 uint32_t digit = 0; 16676 uint32_t digit = 0;
16677 intptr_t str_pos = 0;
16699 for (intptr_t i = 0; i < lsdigit_length; i++) { 16678 for (intptr_t i = 0; i < lsdigit_length; i++) {
16700 char c = str[str_pos++]; 16679 char c = str[str_pos++];
16701 ASSERT(('0' <= c) && (c <= '9')); 16680 ASSERT(('0' <= c) && (c <= '9'));
16702 digit = digit * 10 + c - '0'; 16681 digit = digit * 10 + c - '0';
16703 } 16682 }
16704 result.SetDigitAt(0, digit); 16683 SetDigitAt(digits, 0, digit);
16705 intptr_t used = 1; 16684 intptr_t used_ = 1;
16706
16707 // Read kDecDigitsPerIteration at a time, and store it in 'digit'. 16685 // Read kDecDigitsPerIteration at a time, and store it in 'digit'.
16708 // Then multiply the temporary result by 10^kDecDigitsPerIteration and add 16686 // Then multiply the temporary result by 10^kDecDigitsPerIteration and add
16709 // 'digit' to the new result. 16687 // 'digit' to the new result.
16710 while (str_pos < str_length - 1) { 16688 while (str_pos < str_length - 1) {
16711 digit = 0; 16689 digit = 0;
16712 for (intptr_t i = 0; i < kDecDigitsPerIteration; i++) { 16690 for (intptr_t i = 0; i < kDecDigitsPerIteration; i++) {
16713 char c = str[str_pos++]; 16691 char c = str[str_pos++];
16714 ASSERT(('0' <= c) && (c <= '9')); 16692 ASSERT(('0' <= c) && (c <= '9'));
16715 digit = digit * 10 + c - '0'; 16693 digit = digit * 10 + c - '0';
16716 } 16694 }
16717 // Multiply result with kTenMultiplier and add digit. 16695 // Multiply result with kTenMultiplier and add digit.
16718 for (intptr_t i = 0; i < used; i++) { 16696 for (intptr_t i = 0; i < used_; i++) {
16719 uint64_t product = 16697 uint64_t product =
16720 (static_cast<uint64_t>(result.DigitAt(i)) * kTenMultiplier) + digit; 16698 (static_cast<uint64_t>(DigitAt(digits, i)) * kTenMultiplier) + digit;
16721 result.SetDigitAt(i, static_cast<uint32_t>(product & kDigitMask)); 16699 SetDigitAt(digits, i, static_cast<uint32_t>(product & kDigitMask));
16722 digit = static_cast<uint32_t>(product >> kBitsPerDigit); 16700 digit = static_cast<uint32_t>(product >> kBitsPerDigit);
16723 } 16701 }
16724 result.SetDigitAt(used++, digit); 16702 SetDigitAt(digits, used_++, digit);
16725 } 16703 }
16726 result.SetUsed(used); 16704 *used = used_;
16727 result.Clamp(); 16705 return digits.raw();
16728 return result.raw();
16729 } 16706 }
16730 16707
16731 16708
16732 static double Uint64ToDouble(uint64_t x) { 16709 static double Uint64ToDouble(uint64_t x) {
16733 #if _WIN64 16710 #if _WIN64
16734 // For static_cast<double>(x) MSVC x64 generates 16711 // For static_cast<double>(x) MSVC x64 generates
16735 // 16712 //
16736 // cvtsi2sd xmm0, rax 16713 // cvtsi2sd xmm0, rax
16737 // test rax, rax 16714 // test rax, rax
16738 // jns done 16715 // jns done
(...skipping 29 matching lines...) Expand all
16768 return half + half; 16745 return half + half;
16769 } 16746 }
16770 #else 16747 #else
16771 return static_cast<double>(x); 16748 return static_cast<double>(x);
16772 #endif 16749 #endif
16773 } 16750 }
16774 16751
16775 16752
16776 double Bigint::AsDoubleValue() const { 16753 double Bigint::AsDoubleValue() const {
16777 ASSERT(kBitsPerDigit == 32); 16754 ASSERT(kBitsPerDigit == 32);
16778 ASSERT(IsClamped());
16779 const intptr_t used = Used(); 16755 const intptr_t used = Used();
16780 if (used == 0) { 16756 if (used == 0) {
16781 return 0.0; 16757 return 0.0;
16782 } 16758 }
16783 if (used <= 2) { 16759 if (used <= 2) {
16784 const uint64_t digit1 = (used > 1) ? DigitAt(1) : 0; 16760 const uint64_t digit1 = (used > 1) ? DigitAt(1) : 0;
16785 const uint64_t abs_value = (digit1 << 32) + DigitAt(0); 16761 const uint64_t abs_value = (digit1 << 32) + DigitAt(0);
16786 const double abs_double_value = Uint64ToDouble(abs_value); 16762 const double abs_double_value = Uint64ToDouble(abs_value);
16787 return Neg() ? -abs_double_value : abs_double_value; 16763 return Neg() ? -abs_double_value : abs_double_value;
16788 } 16764 }
(...skipping 3776 matching lines...) Expand 10 before | Expand all | Expand 10 after
20565 return tag_label.ToCString(); 20541 return tag_label.ToCString();
20566 } 20542 }
20567 20543
20568 20544
20569 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 20545 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
20570 Instance::PrintJSONImpl(stream, ref); 20546 Instance::PrintJSONImpl(stream, ref);
20571 } 20547 }
20572 20548
20573 20549
20574 } // namespace dart 20550 } // namespace dart
OLDNEW
« runtime/lib/bigint.dart ('K') | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698