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

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

Issue 2449013003: Don't allocate on the Dart heap during Bigint::ToCString(). (Closed)
Patch Set: Created 4 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
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/snapshot_test.cc » ('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/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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/snapshot_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698