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

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

Issue 23537003: - Allow the collection of intermediate values during long BigintOperations. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 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
« no previous file with comments | « no previous file | 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 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 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 const Bigint& bigint, uword (*allocator)(intptr_t size)) { 322 const Bigint& bigint, uword (*allocator)(intptr_t size)) {
323 // log10(2) ~= 0.30102999566398114. 323 // log10(2) ~= 0.30102999566398114.
324 const intptr_t kLog2Dividend = 30103; 324 const intptr_t kLog2Dividend = 30103;
325 const intptr_t kLog2Divisor = 100000; 325 const intptr_t kLog2Divisor = 100000;
326 // We remove a small constant for rounding imprecision, the \0 character and 326 // We remove a small constant for rounding imprecision, the \0 character and
327 // the negative sign. 327 // the negative sign.
328 const intptr_t kMaxAllowedDigitLength = 328 const intptr_t kMaxAllowedDigitLength =
329 (kIntptrMax - 10) / kLog2Dividend / kDigitBitSize * kLog2Divisor; 329 (kIntptrMax - 10) / kLog2Dividend / kDigitBitSize * kLog2Divisor;
330 330
331 intptr_t length = bigint.Length(); 331 intptr_t length = bigint.Length();
332 Isolate* isolate = Isolate::Current();
332 if (length >= kMaxAllowedDigitLength) { 333 if (length >= kMaxAllowedDigitLength) {
333 // Use the preallocated out of memory exception to avoid calling 334 // Use the preallocated out of memory exception to avoid calling
334 // into dart code or allocating any code. 335 // into dart code or allocating any code.
335 Isolate* isolate = Isolate::Current();
336 const Instance& exception = 336 const Instance& exception =
337 Instance::Handle(isolate->object_store()->out_of_memory()); 337 Instance::Handle(isolate->object_store()->out_of_memory());
338 Exceptions::Throw(exception); 338 Exceptions::Throw(exception);
339 UNREACHABLE(); 339 UNREACHABLE();
340 } 340 }
341 341
342 // Approximate the size of the resulting string. We prefer overestimating 342 // Approximate the size of the resulting string. We prefer overestimating
343 // to not allocating enough. 343 // to not allocating enough.
344 int64_t bit_length = length * kDigitBitSize; 344 int64_t bit_length = length * kDigitBitSize;
345 ASSERT(bit_length > length); 345 ASSERT(bit_length > length);
(...skipping 17 matching lines...) Expand all
363 ASSERT(pow(10.0, kChunkDigits) == kChunkDivisor); 363 ASSERT(pow(10.0, kChunkDigits) == kChunkDivisor);
364 ASSERT(static_cast<Chunk>(kChunkDivisor) < kDigitMaxValue); 364 ASSERT(static_cast<Chunk>(kChunkDivisor) < kDigitMaxValue);
365 ASSERT(Smi::IsValid(kChunkDivisor)); 365 ASSERT(Smi::IsValid(kChunkDivisor));
366 const Bigint& divisor = Bigint::Handle(NewFromInt64(kChunkDivisor)); 366 const Bigint& divisor = Bigint::Handle(NewFromInt64(kChunkDivisor));
367 367
368 // Rest contains the remaining bigint that needs to be printed. 368 // Rest contains the remaining bigint that needs to be printed.
369 Bigint& rest = Bigint::Handle(bigint.raw()); 369 Bigint& rest = Bigint::Handle(bigint.raw());
370 Bigint& quotient = Bigint::Handle(); 370 Bigint& quotient = Bigint::Handle();
371 Bigint& remainder = Bigint::Handle(); 371 Bigint& remainder = Bigint::Handle();
372 while (!rest.IsZero()) { 372 while (!rest.IsZero()) {
373 HANDLESCOPE(isolate);
373 DivideRemainder(rest, divisor, &quotient, &remainder); 374 DivideRemainder(rest, divisor, &quotient, &remainder);
374 ASSERT(remainder.Length() <= 1); 375 ASSERT(remainder.Length() <= 1);
375 intptr_t part = (remainder.Length() == 1) 376 intptr_t part = (remainder.Length() == 1)
376 ? static_cast<intptr_t>(remainder.GetChunkAt(0)) 377 ? static_cast<intptr_t>(remainder.GetChunkAt(0))
377 : 0; 378 : 0;
378 for (int i = 0; i < kChunkDigits; i++) { 379 for (int i = 0; i < kChunkDigits; i++) {
379 result[result_pos++] = '0' + (part % 10); 380 result[result_pos++] = '0' + (part % 10);
380 part /= 10; 381 part /= 10;
381 } 382 }
382 ASSERT(part == 0); 383 ASSERT(part == 0);
(...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 intptr_t quotient_pos = dividend_length - divisor_length; 1531 intptr_t quotient_pos = dividend_length - divisor_length;
1531 // Find the first quotient-digit. 1532 // Find the first quotient-digit.
1532 // The first digit must be computed separately from the other digits because 1533 // The first digit must be computed separately from the other digits because
1533 // the preconditions for the loop are not yet satisfied. 1534 // the preconditions for the loop are not yet satisfied.
1534 // For simplicity use a shifted divisor, so that the comparison and 1535 // For simplicity use a shifted divisor, so that the comparison and
1535 // subtraction are easier. 1536 // subtraction are easier.
1536 int divisor_shift_amount = dividend_length - divisor_length; 1537 int divisor_shift_amount = dividend_length - divisor_length;
1537 Bigint& shifted_divisor = 1538 Bigint& shifted_divisor =
1538 Bigint::Handle(DigitsShiftLeft(divisor, divisor_shift_amount)); 1539 Bigint::Handle(DigitsShiftLeft(divisor, divisor_shift_amount));
1539 Chunk first_quotient_digit = 0; 1540 Chunk first_quotient_digit = 0;
1541 Isolate* isolate = Isolate::Current();
1540 while (UnsignedCompare(dividend, shifted_divisor) >= 0) { 1542 while (UnsignedCompare(dividend, shifted_divisor) >= 0) {
1543 HANDLESCOPE(isolate);
1541 first_quotient_digit++; 1544 first_quotient_digit++;
1542 dividend = Subtract(dividend, shifted_divisor); 1545 dividend = Subtract(dividend, shifted_divisor);
1543 } 1546 }
1544 quotient->SetChunkAt(quotient_pos--, first_quotient_digit); 1547 quotient->SetChunkAt(quotient_pos--, first_quotient_digit);
1545 1548
1546 // Find the remainder of the digits. 1549 // Find the remainder of the digits.
1547 1550
1548 Chunk first_divisor_digit = divisor.GetChunkAt(divisor_length - 1); 1551 Chunk first_divisor_digit = divisor.GetChunkAt(divisor_length - 1);
1549 // The short divisor only represents the first two digits of the divisor. 1552 // The short divisor only represents the first two digits of the divisor.
1550 // If the divisor has only one digit, then the second part is zeroed out. 1553 // If the divisor has only one digit, then the second part is zeroed out.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1665 int BigintOperations::CountBits(Chunk digit) { 1668 int BigintOperations::CountBits(Chunk digit) {
1666 int result = 0; 1669 int result = 0;
1667 while (digit != 0) { 1670 while (digit != 0) {
1668 digit >>= 1; 1671 digit >>= 1;
1669 result++; 1672 result++;
1670 } 1673 }
1671 return result; 1674 return result;
1672 } 1675 }
1673 1676
1674 } // namespace dart 1677 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698