| 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/become.h" | 10 #include "vm/become.h" |
| (...skipping 19722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19733 } | 19733 } |
| 19734 if (IsNegative()) { | 19734 if (IsNegative()) { |
| 19735 result = -result; | 19735 result = -result; |
| 19736 } | 19736 } |
| 19737 return result > 0 ? 1 : result < 0 ? -1 : 0; | 19737 return result > 0 ? 1 : result < 0 ? -1 : 0; |
| 19738 } | 19738 } |
| 19739 return this->IsNegative() ? -1 : 1; | 19739 return this->IsNegative() ? -1 : 1; |
| 19740 } | 19740 } |
| 19741 | 19741 |
| 19742 | 19742 |
| 19743 const char* Bigint::ToDecCString(uword (*allocator)(intptr_t size)) const { | 19743 const char* Bigint::ToDecCString(Zone* zone) const { |
| 19744 // log10(2) ~= 0.30102999566398114. | 19744 // log10(2) ~= 0.30102999566398114. |
| 19745 const intptr_t kLog2Dividend = 30103; | 19745 const intptr_t kLog2Dividend = 30103; |
| 19746 const intptr_t kLog2Divisor = 100000; | 19746 const intptr_t kLog2Divisor = 100000; |
| 19747 intptr_t used = Used(); | 19747 intptr_t used = Used(); |
| 19748 const intptr_t kMaxUsed = | 19748 const intptr_t kMaxUsed = |
| 19749 kIntptrMax / kBitsPerDigit / kLog2Dividend * kLog2Divisor; | 19749 kIntptrMax / kBitsPerDigit / kLog2Dividend * kLog2Divisor; |
| 19750 if (used > kMaxUsed) { | 19750 if (used > kMaxUsed) { |
| 19751 Exceptions::ThrowOOM(); | 19751 Exceptions::ThrowOOM(); |
| 19752 UNREACHABLE(); | 19752 UNREACHABLE(); |
| 19753 } | 19753 } |
| 19754 const int64_t bit_len = used * kBitsPerDigit; | 19754 const int64_t bit_len = used * kBitsPerDigit; |
| 19755 const int64_t dec_len = (bit_len * kLog2Dividend / kLog2Divisor) + 1; | 19755 const int64_t dec_len = (bit_len * kLog2Dividend / kLog2Divisor) + 1; |
| 19756 // Add one byte for the minus sign and for the trailing \0 character. | 19756 // Add one byte for the minus sign and for the trailing \0 character. |
| 19757 const int64_t len = (Neg() ? 1 : 0) + dec_len + 1; | 19757 const int64_t len = (Neg() ? 1 : 0) + dec_len + 1; |
| 19758 char* chars = reinterpret_cast<char*>(allocator(len)); | 19758 char* chars = zone->Alloc<char>(len); |
| 19759 intptr_t pos = 0; | 19759 intptr_t pos = 0; |
| 19760 const intptr_t kDivisor = 100000000; | 19760 const intptr_t kDivisor = 100000000; |
| 19761 const intptr_t kDigits = 8; | 19761 const intptr_t kDigits = 8; |
| 19762 ASSERT(pow(10.0, 1.0 * kDigits) == kDivisor); | 19762 ASSERT(pow(10.0, 1.0 * kDigits) == kDivisor); |
| 19763 ASSERT(kDivisor < kDigitBase); | 19763 ASSERT(kDivisor < kDigitBase); |
| 19764 ASSERT(Smi::IsValid(kDivisor)); | 19764 ASSERT(Smi::IsValid(kDivisor)); |
| 19765 // Allocate a copy of the digits. | 19765 // Allocate a copy of the digits. |
| 19766 const TypedData& rest_digits = TypedData::Handle( | 19766 uint32_t* rest_digits = zone->Alloc<uint32_t>(used); |
| 19767 TypedData::New(kTypedDataUint32ArrayCid, used)); | |
| 19768 for (intptr_t i = 0; i < used; i++) { | 19767 for (intptr_t i = 0; i < used; i++) { |
| 19769 rest_digits.SetUint32(i << 2, DigitAt(i)); | 19768 rest_digits[i] = DigitAt(i); |
| 19770 } | 19769 } |
| 19771 if (used == 0) { | 19770 if (used == 0) { |
| 19772 chars[pos++] = '0'; | 19771 chars[pos++] = '0'; |
| 19773 } | 19772 } |
| 19774 while (used > 0) { | 19773 while (used > 0) { |
| 19775 uint32_t remainder = 0; | 19774 uint32_t remainder = 0; |
| 19776 for (intptr_t i = used - 1; i >= 0; i--) { | 19775 for (intptr_t i = used - 1; i >= 0; i--) { |
| 19777 uint64_t dividend = (static_cast<uint64_t>(remainder) << kBitsPerDigit) + | 19776 uint64_t dividend = (static_cast<uint64_t>(remainder) << kBitsPerDigit) + |
| 19778 rest_digits.GetUint32(i << 2); | 19777 rest_digits[i]; |
| 19779 uint32_t quotient = static_cast<uint32_t>(dividend / kDivisor); | 19778 uint32_t quotient = static_cast<uint32_t>(dividend / kDivisor); |
| 19780 remainder = static_cast<uint32_t>( | 19779 remainder = static_cast<uint32_t>( |
| 19781 dividend - static_cast<uint64_t>(quotient) * kDivisor); | 19780 dividend - static_cast<uint64_t>(quotient) * kDivisor); |
| 19782 rest_digits.SetUint32(i << 2, quotient); | 19781 rest_digits[i] = quotient; |
| 19783 } | 19782 } |
| 19784 // Clamp rest_digits. | 19783 // Clamp rest_digits. |
| 19785 while ((used > 0) && (rest_digits.GetUint32((used - 1) << 2) == 0)) { | 19784 while ((used > 0) && (rest_digits[used - 1] == 0)) { |
| 19786 used--; | 19785 used--; |
| 19787 } | 19786 } |
| 19788 for (intptr_t i = 0; i < kDigits; i++) { | 19787 for (intptr_t i = 0; i < kDigits; i++) { |
| 19789 chars[pos++] = '0' + (remainder % 10); | 19788 chars[pos++] = '0' + (remainder % 10); |
| 19790 remainder /= 10; | 19789 remainder /= 10; |
| 19791 } | 19790 } |
| 19792 ASSERT(remainder == 0); | 19791 ASSERT(remainder == 0); |
| 19793 } | 19792 } |
| 19794 // Remove leading zeros. | 19793 // Remove leading zeros. |
| 19795 while ((pos > 1) && (chars[pos - 1] == '0')) { | 19794 while ((pos > 1) && (chars[pos - 1] == '0')) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 19806 chars[i] = chars[j]; | 19805 chars[i] = chars[j]; |
| 19807 chars[j] = tmp; | 19806 chars[j] = tmp; |
| 19808 i++; | 19807 i++; |
| 19809 j--; | 19808 j--; |
| 19810 } | 19809 } |
| 19811 chars[pos] = '\0'; | 19810 chars[pos] = '\0'; |
| 19812 return chars; | 19811 return chars; |
| 19813 } | 19812 } |
| 19814 | 19813 |
| 19815 | 19814 |
| 19816 const char* Bigint::ToHexCString(uword (*allocator)(intptr_t size)) const { | 19815 const char* Bigint::ToHexCString(Zone* zone) const { |
| 19817 const intptr_t used = Used(); | 19816 const intptr_t used = Used(); |
| 19818 if (used == 0) { | 19817 if (used == 0) { |
| 19819 const char* zero = "0x0"; | 19818 const char* zero = "0x0"; |
| 19820 const size_t len = strlen(zero) + 1; | 19819 const size_t len = strlen(zero) + 1; |
| 19821 char* chars = reinterpret_cast<char*>(allocator(len)); | 19820 char* chars = zone->Alloc<char>(len); |
| 19822 strncpy(chars, zero, len); | 19821 strncpy(chars, zero, len); |
| 19823 return chars; | 19822 return chars; |
| 19824 } | 19823 } |
| 19825 const int kBitsPerHexDigit = 4; | 19824 const int kBitsPerHexDigit = 4; |
| 19826 const int kHexDigitsPerDigit = 8; | 19825 const int kHexDigitsPerDigit = 8; |
| 19827 const intptr_t kMaxUsed = (kIntptrMax - 4) / kHexDigitsPerDigit; | 19826 const intptr_t kMaxUsed = (kIntptrMax - 4) / kHexDigitsPerDigit; |
| 19828 if (used > kMaxUsed) { | 19827 if (used > kMaxUsed) { |
| 19829 Exceptions::ThrowOOM(); | 19828 Exceptions::ThrowOOM(); |
| 19830 UNREACHABLE(); | 19829 UNREACHABLE(); |
| 19831 } | 19830 } |
| 19832 intptr_t hex_len = (used - 1) * kHexDigitsPerDigit; | 19831 intptr_t hex_len = (used - 1) * kHexDigitsPerDigit; |
| 19833 // The most significant digit may use fewer than kHexDigitsPerDigit digits. | 19832 // The most significant digit may use fewer than kHexDigitsPerDigit digits. |
| 19834 uint32_t digit = DigitAt(used - 1); | 19833 uint32_t digit = DigitAt(used - 1); |
| 19835 ASSERT(digit != 0); // Value must be clamped. | 19834 ASSERT(digit != 0); // Value must be clamped. |
| 19836 while (digit != 0) { | 19835 while (digit != 0) { |
| 19837 hex_len++; | 19836 hex_len++; |
| 19838 digit >>= kBitsPerHexDigit; | 19837 digit >>= kBitsPerHexDigit; |
| 19839 } | 19838 } |
| 19840 // Add bytes for '0x', for the minus sign, and for the trailing \0 character. | 19839 // Add bytes for '0x', for the minus sign, and for the trailing \0 character. |
| 19841 const int32_t len = (Neg() ? 1 : 0) + 2 + hex_len + 1; | 19840 const int32_t len = (Neg() ? 1 : 0) + 2 + hex_len + 1; |
| 19842 char* chars = reinterpret_cast<char*>(allocator(len)); | 19841 char* chars = zone->Alloc<char>(len); |
| 19843 intptr_t pos = len; | 19842 intptr_t pos = len; |
| 19844 chars[--pos] = '\0'; | 19843 chars[--pos] = '\0'; |
| 19845 for (intptr_t i = 0; i < (used - 1); i++) { | 19844 for (intptr_t i = 0; i < (used - 1); i++) { |
| 19846 digit = DigitAt(i); | 19845 digit = DigitAt(i); |
| 19847 for (intptr_t j = 0; j < kHexDigitsPerDigit; j++) { | 19846 for (intptr_t j = 0; j < kHexDigitsPerDigit; j++) { |
| 19848 chars[--pos] = Utils::IntToHexDigit(digit & 0xf); | 19847 chars[--pos] = Utils::IntToHexDigit(digit & 0xf); |
| 19849 digit >>= kBitsPerHexDigit; | 19848 digit >>= kBitsPerHexDigit; |
| 19850 } | 19849 } |
| 19851 } | 19850 } |
| 19852 digit = DigitAt(used - 1); | 19851 digit = DigitAt(used - 1); |
| 19853 while (digit != 0) { | 19852 while (digit != 0) { |
| 19854 chars[--pos] = Utils::IntToHexDigit(digit & 0xf); | 19853 chars[--pos] = Utils::IntToHexDigit(digit & 0xf); |
| 19855 digit >>= kBitsPerHexDigit; | 19854 digit >>= kBitsPerHexDigit; |
| 19856 } | 19855 } |
| 19857 chars[--pos] = 'x'; | 19856 chars[--pos] = 'x'; |
| 19858 chars[--pos] = '0'; | 19857 chars[--pos] = '0'; |
| 19859 if (Neg()) { | 19858 if (Neg()) { |
| 19860 chars[--pos] = '-'; | 19859 chars[--pos] = '-'; |
| 19861 } | 19860 } |
| 19862 ASSERT(pos == 0); | 19861 ASSERT(pos == 0); |
| 19863 return chars; | 19862 return chars; |
| 19864 } | 19863 } |
| 19865 | 19864 |
| 19866 | 19865 |
| 19867 static uword BigintAllocator(intptr_t size) { | |
| 19868 Zone* zone = Thread::Current()->zone(); | |
| 19869 return zone->AllocUnsafe(size); | |
| 19870 } | |
| 19871 | |
| 19872 | |
| 19873 const char* Bigint::ToCString() const { | 19866 const char* Bigint::ToCString() const { |
| 19874 return ToDecCString(&BigintAllocator); | 19867 return ToDecCString(Thread::Current()->zone()); |
| 19875 } | 19868 } |
| 19876 | 19869 |
| 19877 | 19870 |
| 19878 // Synchronize with implementation in compiler (intrinsifier). | 19871 // Synchronize with implementation in compiler (intrinsifier). |
| 19879 class StringHasher : ValueObject { | 19872 class StringHasher : ValueObject { |
| 19880 public: | 19873 public: |
| 19881 StringHasher() : hash_(0) {} | 19874 StringHasher() : hash_(0) {} |
| 19882 void Add(int32_t ch) { | 19875 void Add(int32_t ch) { |
| 19883 hash_ = CombineHashes(hash_, ch); | 19876 hash_ = CombineHashes(hash_, ch); |
| 19884 } | 19877 } |
| (...skipping 3150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 23035 return UserTag::null(); | 23028 return UserTag::null(); |
| 23036 } | 23029 } |
| 23037 | 23030 |
| 23038 | 23031 |
| 23039 const char* UserTag::ToCString() const { | 23032 const char* UserTag::ToCString() const { |
| 23040 const String& tag_label = String::Handle(label()); | 23033 const String& tag_label = String::Handle(label()); |
| 23041 return tag_label.ToCString(); | 23034 return tag_label.ToCString(); |
| 23042 } | 23035 } |
| 23043 | 23036 |
| 23044 } // namespace dart | 23037 } // namespace dart |
| OLD | NEW |