Chromium Code Reviews| 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/assert.h" | |
| 5 #include "platform/utils.h" | 6 #include "platform/utils.h" |
| 6 | 7 |
| 7 #include "vm/double_internals.h" | 8 #include "vm/double_internals.h" |
| 8 #include "vm/exceptions.h" | 9 #include "vm/exceptions.h" |
| 9 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| 10 #include "vm/zone.h" | 11 #include "vm/zone.h" |
| 11 | 12 |
| 12 namespace dart { | 13 namespace dart { |
| 13 | 14 |
| 14 RawBigint* BigintOperations::NewFromSmi(const Smi& smi, Heap::Space space) { | 15 RawBigint* BigintOperations::NewFromSmi(const Smi& smi, Heap::Space space) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 // recursive call is not negative. | 100 // recursive call is not negative. |
| 100 // We don't catch leading '-'s for zero. Ex: "--0", or "---". | 101 // We don't catch leading '-'s for zero. Ex: "--0", or "---". |
| 101 if (str[0] == '-') { | 102 if (str[0] == '-') { |
| 102 const Bigint& result = Bigint::Handle(NewFromCString(&str[1], space)); | 103 const Bigint& result = Bigint::Handle(NewFromCString(&str[1], space)); |
| 103 result.ToggleSign(); | 104 result.ToggleSign(); |
| 104 ASSERT(result.IsZero() || result.IsNegative()); | 105 ASSERT(result.IsZero() || result.IsNegative()); |
| 105 ASSERT(IsClamped(result)); | 106 ASSERT(IsClamped(result)); |
| 106 return result.raw(); | 107 return result.raw(); |
| 107 } | 108 } |
| 108 | 109 |
| 109 intptr_t str_length = strlen(str); | 110 const intptr_t str_length = strlen(str); |
| 111 if (str_length < 0) { | |
|
sra1
2013/09/17 05:32:31
I don't understand the purpose of this test.
If s
Michael Lippautz (Google)
2013/09/17 17:10:35
Replaced with a comment saying why we don't need a
| |
| 112 FATAL("Fatal error in BigintOperations::NewFromCString: string too long"); | |
| 113 } | |
| 110 if ((str_length > 2) && | 114 if ((str_length > 2) && |
| 111 (str[0] == '0') && | 115 (str[0] == '0') && |
| 112 ((str[1] == 'x') || (str[1] == 'X'))) { | 116 ((str[1] == 'x') || (str[1] == 'X'))) { |
| 113 const Bigint& result = Bigint::Handle(FromHexCString(&str[2], space)); | 117 const Bigint& result = Bigint::Handle(FromHexCString(&str[2], space)); |
| 114 ASSERT(IsClamped(result)); | 118 ASSERT(IsClamped(result)); |
| 115 return result.raw(); | 119 return result.raw(); |
| 116 } else { | 120 } else { |
| 117 return FromDecimalCString(str, space); | 121 return FromDecimalCString(str, space); |
| 118 } | 122 } |
| 119 } | 123 } |
| 120 | 124 |
| 121 | 125 |
| 122 intptr_t BigintOperations::ComputeChunkLength(const char* hex_string) { | 126 intptr_t BigintOperations::ComputeChunkLength(const char* hex_string) { |
| 123 ASSERT(kDigitBitSize % 4 == 0); | 127 ASSERT(kDigitBitSize % 4 == 0); |
| 124 intptr_t hex_length = strlen(hex_string); | 128 const intptr_t hex_length = strlen(hex_string); |
| 129 if (hex_length < 0) { | |
| 130 FATAL("Fatal error in BigintOperations::ComputeChunkLength: " | |
| 131 "string too long"); | |
| 132 } | |
| 125 // Round up. | 133 // Round up. |
| 126 intptr_t bigint_length = ((hex_length - 1) / kHexCharsPerDigit) + 1; | 134 intptr_t bigint_length = ((hex_length - 1) / kHexCharsPerDigit) + 1; |
| 127 return bigint_length; | 135 return bigint_length; |
| 128 } | 136 } |
| 129 | 137 |
| 130 | 138 |
| 131 RawBigint* BigintOperations::FromHexCString(const char* hex_string, | 139 RawBigint* BigintOperations::FromHexCString(const char* hex_string, |
| 132 Heap::Space space) { | 140 Heap::Space space) { |
| 133 // If the string starts with '-' recursively restart the whole operation | 141 // If the string starts with '-' recursively restart the whole operation |
| 134 // without the character and then toggle the sign. | 142 // without the character and then toggle the sign. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 151 | 159 |
| 152 | 160 |
| 153 RawBigint* BigintOperations::FromDecimalCString(const char* str, | 161 RawBigint* BigintOperations::FromDecimalCString(const char* str, |
| 154 Heap::Space space) { | 162 Heap::Space space) { |
| 155 Isolate* isolate = Isolate::Current(); | 163 Isolate* isolate = Isolate::Current(); |
| 156 // Read 8 digits a time. 10^8 < 2^27. | 164 // Read 8 digits a time. 10^8 < 2^27. |
| 157 const int kDigitsPerIteration = 8; | 165 const int kDigitsPerIteration = 8; |
| 158 const Chunk kTenMultiplier = 100000000; | 166 const Chunk kTenMultiplier = 100000000; |
| 159 ASSERT(kDigitBitSize >= 27); | 167 ASSERT(kDigitBitSize >= 27); |
| 160 | 168 |
| 161 intptr_t str_length = strlen(str); | 169 const intptr_t str_length = strlen(str); |
| 170 if (str_length < 0) { | |
| 171 FATAL("Fatal error in BigintOperations::FromDecimalCString: " | |
| 172 "string too long"); | |
| 173 } | |
| 162 intptr_t str_pos = 0; | 174 intptr_t str_pos = 0; |
| 163 | 175 |
| 164 // Read first digit separately. This avoids a multiplication and addition. | 176 // Read first digit separately. This avoids a multiplication and addition. |
| 165 // The first digit might also not have kDigitsPerIteration decimal digits. | 177 // The first digit might also not have kDigitsPerIteration decimal digits. |
| 166 int first_digit_decimal_digits = str_length % kDigitsPerIteration; | 178 int first_digit_decimal_digits = str_length % kDigitsPerIteration; |
| 167 Chunk digit = 0; | 179 Chunk digit = 0; |
| 168 for (intptr_t i = 0; i < first_digit_decimal_digits; i++) { | 180 for (intptr_t i = 0; i < first_digit_decimal_digits; i++) { |
| 169 char c = str[str_pos++]; | 181 char c = str[str_pos++]; |
| 170 ASSERT(('0' <= c) && (c <= '9')); | 182 ASSERT(('0' <= c) && (c <= '9')); |
| 171 digit = digit * 10 + c - '0'; | 183 digit = digit * 10 + c - '0'; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 | 252 |
| 241 | 253 |
| 242 const char* BigintOperations::ToHexCString(intptr_t length, | 254 const char* BigintOperations::ToHexCString(intptr_t length, |
| 243 bool is_negative, | 255 bool is_negative, |
| 244 void* data, | 256 void* data, |
| 245 uword (*allocator)(intptr_t size)) { | 257 uword (*allocator)(intptr_t size)) { |
| 246 NoGCScope no_gc; | 258 NoGCScope no_gc; |
| 247 | 259 |
| 248 ASSERT(kDigitBitSize % 4 == 0); | 260 ASSERT(kDigitBitSize % 4 == 0); |
| 249 | 261 |
| 250 intptr_t chunk_length = length; | 262 // Conservative maximum chunk length. |
| 263 const intptr_t kMaxChunkLen = | |
| 264 (kIntptrMax - 2 /* 0x */ | |
| 265 - 1 /* trailing '\0' */ | |
| 266 - 1 /* leading '-' */) / kHexCharsPerDigit; | |
| 267 const intptr_t chunk_length = length; | |
| 268 // Conservative check assuming leading bigint-digit also takes up | |
| 269 // kHexCharsPerDigit. | |
| 270 if (chunk_length > kMaxChunkLen) { | |
| 271 FATAL("Fatal error in BigintOperations::ToHexCString: string too long"); | |
| 272 } | |
| 251 Chunk* chunk_data = reinterpret_cast<Chunk*>(data); | 273 Chunk* chunk_data = reinterpret_cast<Chunk*>(data); |
| 252 if (length == 0) { | 274 if (length == 0) { |
| 253 const char* zero = "0x0"; | 275 const char* zero = "0x0"; |
| 254 const int kLength = strlen(zero); | 276 const intptr_t kLength = strlen(zero); |
| 255 char* result = reinterpret_cast<char*>(allocator(kLength + 1)); | 277 char* result = reinterpret_cast<char*>(allocator(kLength + 1)); |
| 256 ASSERT(result != NULL); | 278 ASSERT(result != NULL); |
| 257 memmove(result, zero, kLength); | 279 memmove(result, zero, kLength); |
| 258 result[kLength] = '\0'; | 280 result[kLength] = '\0'; |
| 259 return result; | 281 return result; |
| 260 } | 282 } |
| 261 ASSERT(chunk_data != NULL); | 283 ASSERT(chunk_data != NULL); |
| 262 | 284 |
| 263 // Compute the number of hex-digits that are needed to represent the | 285 // Compute the number of hex-digits that are needed to represent the |
| 264 // leading bigint-digit. All other digits need exactly kHexCharsPerDigit | 286 // leading bigint-digit. All other digits need exactly kHexCharsPerDigit |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 const char* BigintOperations::ToDecimalCString( | 345 const char* BigintOperations::ToDecimalCString( |
| 324 const Bigint& bigint, uword (*allocator)(intptr_t size)) { | 346 const Bigint& bigint, uword (*allocator)(intptr_t size)) { |
| 325 // log10(2) ~= 0.30102999566398114. | 347 // log10(2) ~= 0.30102999566398114. |
| 326 const intptr_t kLog2Dividend = 30103; | 348 const intptr_t kLog2Dividend = 30103; |
| 327 const intptr_t kLog2Divisor = 100000; | 349 const intptr_t kLog2Divisor = 100000; |
| 328 // We remove a small constant for rounding imprecision, the \0 character and | 350 // We remove a small constant for rounding imprecision, the \0 character and |
| 329 // the negative sign. | 351 // the negative sign. |
| 330 const intptr_t kMaxAllowedDigitLength = | 352 const intptr_t kMaxAllowedDigitLength = |
| 331 (kIntptrMax - 10) / kLog2Dividend / kDigitBitSize * kLog2Divisor; | 353 (kIntptrMax - 10) / kLog2Dividend / kDigitBitSize * kLog2Divisor; |
| 332 | 354 |
| 333 intptr_t length = bigint.Length(); | 355 const intptr_t length = bigint.Length(); |
| 334 Isolate* isolate = Isolate::Current(); | 356 Isolate* isolate = Isolate::Current(); |
| 335 if (length >= kMaxAllowedDigitLength) { | 357 if (length >= kMaxAllowedDigitLength) { |
| 336 // Use the preallocated out of memory exception to avoid calling | 358 // Use the preallocated out of memory exception to avoid calling |
| 337 // into dart code or allocating any code. | 359 // into dart code or allocating any code. |
| 338 const Instance& exception = | 360 const Instance& exception = |
| 339 Instance::Handle(isolate->object_store()->out_of_memory()); | 361 Instance::Handle(isolate->object_store()->out_of_memory()); |
| 340 Exceptions::Throw(exception); | 362 Exceptions::Throw(exception); |
| 341 UNREACHABLE(); | 363 UNREACHABLE(); |
| 342 } | 364 } |
| 343 | 365 |
| (...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1334 | 1356 |
| 1335 | 1357 |
| 1336 void BigintOperations::FromHexCString(const char* hex_string, | 1358 void BigintOperations::FromHexCString(const char* hex_string, |
| 1337 const Bigint& value) { | 1359 const Bigint& value) { |
| 1338 ASSERT(hex_string[0] != '-'); | 1360 ASSERT(hex_string[0] != '-'); |
| 1339 intptr_t bigint_length = ComputeChunkLength(hex_string); | 1361 intptr_t bigint_length = ComputeChunkLength(hex_string); |
| 1340 // The bigint's least significant digit (lsd) is at position 0, whereas the | 1362 // The bigint's least significant digit (lsd) is at position 0, whereas the |
| 1341 // given string has it's lsd at the last position. | 1363 // given string has it's lsd at the last position. |
| 1342 // The hex_i index, pointing into the string, starts therefore at the end, | 1364 // The hex_i index, pointing into the string, starts therefore at the end, |
| 1343 // whereas the bigint-index (i) starts at 0. | 1365 // whereas the bigint-index (i) starts at 0. |
| 1344 intptr_t hex_length = strlen(hex_string); | 1366 const intptr_t hex_length = strlen(hex_string); |
| 1367 if (hex_length < 0) { | |
| 1368 FATAL("Fatal error in BigintOperations::FromHexCString: string too long"); | |
| 1369 } | |
| 1345 intptr_t hex_i = hex_length - 1; | 1370 intptr_t hex_i = hex_length - 1; |
| 1346 for (intptr_t i = 0; i < bigint_length; i++) { | 1371 for (intptr_t i = 0; i < bigint_length; i++) { |
| 1347 Chunk digit = 0; | 1372 Chunk digit = 0; |
| 1348 int shift = 0; | 1373 int shift = 0; |
| 1349 for (int j = 0; j < kHexCharsPerDigit; j++) { | 1374 for (int j = 0; j < kHexCharsPerDigit; j++) { |
| 1350 // Reads a block of hexadecimal digits and stores it in 'digit'. | 1375 // Reads a block of hexadecimal digits and stores it in 'digit'. |
| 1351 // Ex: "0123456" with kHexCharsPerDigit == 3, hex_i == 6, reads "456". | 1376 // Ex: "0123456" with kHexCharsPerDigit == 3, hex_i == 6, reads "456". |
| 1352 if (hex_i < 0) { | 1377 if (hex_i < 0) { |
| 1353 break; | 1378 break; |
| 1354 } | 1379 } |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1748 int BigintOperations::CountBits(Chunk digit) { | 1773 int BigintOperations::CountBits(Chunk digit) { |
| 1749 int result = 0; | 1774 int result = 0; |
| 1750 while (digit != 0) { | 1775 while (digit != 0) { |
| 1751 digit >>= 1; | 1776 digit >>= 1; |
| 1752 result++; | 1777 result++; |
| 1753 } | 1778 } |
| 1754 return result; | 1779 return result; |
| 1755 } | 1780 } |
| 1756 | 1781 |
| 1757 } // namespace dart | 1782 } // namespace dart |
| OLD | NEW |