OLD | NEW |
1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 | 2 |
3 #include "vm/bigint_operations.h" | 3 #include "vm/bigint_operations.h" |
4 | 4 |
5 #include "platform/utils.h" | 5 #include "platform/utils.h" |
6 | 6 |
7 #include "vm/double_internals.h" | 7 #include "vm/double_internals.h" |
8 #include "vm/exceptions.h" | 8 #include "vm/exceptions.h" |
9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
10 #include "vm/zone.h" | 10 #include "vm/zone.h" |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 } | 107 } |
108 | 108 |
109 intptr_t str_length = strlen(str); | 109 intptr_t str_length = strlen(str); |
110 if ((str_length > 2) && | 110 if ((str_length > 2) && |
111 (str[0] == '0') && | 111 (str[0] == '0') && |
112 ((str[1] == 'x') || (str[1] == 'X'))) { | 112 ((str[1] == 'x') || (str[1] == 'X'))) { |
113 const Bigint& result = Bigint::Handle(FromHexCString(&str[2], space)); | 113 const Bigint& result = Bigint::Handle(FromHexCString(&str[2], space)); |
114 ASSERT(IsClamped(result)); | 114 ASSERT(IsClamped(result)); |
115 return result.raw(); | 115 return result.raw(); |
116 } else { | 116 } else { |
117 return FromDecimalCString(str); | 117 return FromDecimalCString(str, space); |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 | 121 |
122 intptr_t BigintOperations::ComputeChunkLength(const char* hex_string) { | 122 intptr_t BigintOperations::ComputeChunkLength(const char* hex_string) { |
123 ASSERT(kDigitBitSize % 4 == 0); | 123 ASSERT(kDigitBitSize % 4 == 0); |
124 intptr_t hex_length = strlen(hex_string); | 124 intptr_t hex_length = strlen(hex_string); |
125 // Round up. | 125 // Round up. |
126 intptr_t bigint_length = ((hex_length - 1) / kHexCharsPerDigit) + 1; | 126 intptr_t bigint_length = ((hex_length - 1) / kHexCharsPerDigit) + 1; |
127 return bigint_length; | 127 return bigint_length; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 162 |
163 // Read first digit separately. This avoids a multiplication and addition. | 163 // Read first digit separately. This avoids a multiplication and addition. |
164 // The first digit might also not have kDigitsPerIteration decimal digits. | 164 // The first digit might also not have kDigitsPerIteration decimal digits. |
165 int first_digit_decimal_digits = str_length % kDigitsPerIteration; | 165 int first_digit_decimal_digits = str_length % kDigitsPerIteration; |
166 Chunk digit = 0; | 166 Chunk digit = 0; |
167 for (intptr_t i = 0; i < first_digit_decimal_digits; i++) { | 167 for (intptr_t i = 0; i < first_digit_decimal_digits; i++) { |
168 char c = str[str_pos++]; | 168 char c = str[str_pos++]; |
169 ASSERT(('0' <= c) && (c <= '9')); | 169 ASSERT(('0' <= c) && (c <= '9')); |
170 digit = digit * 10 + c - '0'; | 170 digit = digit * 10 + c - '0'; |
171 } | 171 } |
172 Bigint& result = Bigint::Handle(Bigint::Allocate(1, space)); | 172 Bigint& result = Bigint::Handle(Bigint::Allocate(1)); |
173 result.SetChunkAt(0, digit); | 173 result.SetChunkAt(0, digit); |
174 Clamp(result); // Multiplication requires the inputs to be clamped. | 174 Clamp(result); // Multiplication requires the inputs to be clamped. |
175 | 175 |
176 // Read kDigitsPerIteration at a time, and store it in 'increment'. | 176 // Read kDigitsPerIteration at a time, and store it in 'increment'. |
177 // Then multiply the temporary result by 10^kDigitsPerIteration and add | 177 // Then multiply the temporary result by 10^kDigitsPerIteration and add |
178 // 'increment' to the new result. | 178 // 'increment' to the new result. |
179 const Bigint& increment = Bigint::Handle(Bigint::Allocate(1, space)); | 179 const Bigint& increment = Bigint::Handle(Bigint::Allocate(1)); |
180 while (str_pos < str_length - 1) { | 180 while (str_pos < str_length - 1) { |
181 Chunk digit = 0; | 181 Chunk digit = 0; |
182 for (intptr_t i = 0; i < kDigitsPerIteration; i++) { | 182 for (intptr_t i = 0; i < kDigitsPerIteration; i++) { |
183 char c = str[str_pos++]; | 183 char c = str[str_pos++]; |
184 ASSERT(('0' <= c) && (c <= '9')); | 184 ASSERT(('0' <= c) && (c <= '9')); |
185 digit = digit * 10 + c - '0'; | 185 digit = digit * 10 + c - '0'; |
186 } | 186 } |
187 result ^= MultiplyWithDigit(result, kTenMultiplier); | 187 result ^= MultiplyWithDigit(result, kTenMultiplier); |
188 if (digit != 0) { | 188 if (digit != 0) { |
189 increment.SetChunkAt(0, digit); | 189 increment.SetChunkAt(0, digit); |
190 result ^= Add(result, increment); | 190 result ^= Add(result, increment); |
191 } | 191 } |
192 } | 192 } |
193 Clamp(result); | 193 Clamp(result); |
| 194 if ((space == Heap::kOld) && !result.IsOld()) { |
| 195 result ^= Object::Clone(result, Heap::kOld); |
| 196 } |
194 return result.raw(); | 197 return result.raw(); |
195 } | 198 } |
196 | 199 |
197 | 200 |
198 RawBigint* BigintOperations::NewFromDouble(double d, Heap::Space space) { | 201 RawBigint* BigintOperations::NewFromDouble(double d, Heap::Space space) { |
199 if ((-1.0 < d) && (d < 1.0)) { | 202 if ((-1.0 < d) && (d < 1.0)) { |
200 // Shortcut for small numbers. Also makes the right-shift below | 203 // Shortcut for small numbers. Also makes the right-shift below |
201 // well specified. | 204 // well specified. |
202 Smi& zero = Smi::Handle(Smi::New(0)); | 205 Smi& zero = Smi::Handle(Smi::New(0)); |
203 return NewFromSmi(zero, space); | 206 return NewFromSmi(zero, space); |
(...skipping 1441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1645 int BigintOperations::CountBits(Chunk digit) { | 1648 int BigintOperations::CountBits(Chunk digit) { |
1646 int result = 0; | 1649 int result = 0; |
1647 while (digit != 0) { | 1650 while (digit != 0) { |
1648 digit >>= 1; | 1651 digit >>= 1; |
1649 result++; | 1652 result++; |
1650 } | 1653 } |
1651 return result; | 1654 return result; |
1652 } | 1655 } |
1653 | 1656 |
1654 } // namespace dart | 1657 } // namespace dart |
OLD | NEW |