Changeset 231137 in webkit
- Timestamp:
- Apr 28, 2018 10:37:21 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 7 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r231133 r231137 1 2018-04-28 Caio Lima <ticaiolima@gmail.com> 2 3 [ESNext][BigInt] Implement support for "*" operation 4 https://bugs.webkit.org/show_bug.cgi?id=183721 5 6 Reviewed by Saam Barati. 7 8 * bigIntTests.yaml: 9 * stress/big-int-mul-jit.js: Added. 10 * stress/big-int-mul-to-primitive-precedence.js: Added. 11 * stress/big-int-mul-to-primitive.js: Added. 12 * stress/big-int-mul-type-error.js: Added. 13 * stress/big-int-mul-wrapped-value.js: Added. 14 * stress/big-int-multiplication.js: Added. 15 * stress/big-int-multiply-memory-stress.js: Added. 16 1 17 2018-04-28 Commit Queue <commit-queue@webkit.org> 2 18 -
trunk/JSTests/bigIntTests.yaml
r231133 r231137 98 98 cmd: runBigIntEnabled 99 99 100 - path: stress/big-int-mul-jit.js 101 cmd: runBigIntEnabled 102 103 - path: stress/big-int-mul-to-primitive-precedence.js 104 cmd: runBigIntEnabled 105 106 - path: stress/big-int-mul-to-primitive.js 107 cmd: runBigIntEnabled 108 109 - path: stress/big-int-mul-type-error.js 110 cmd: runBigIntEnabled 111 112 - path: stress/big-int-mul-wrapped-value.js 113 cmd: runBigIntEnabled 114 115 - path: stress/big-int-multiplication.js 116 cmd: runBigIntEnabled 117 118 - path: stress/big-int-multiply-memory-stress.js 119 cmd: runBigIntEnabled 120 -
trunk/Source/JavaScriptCore/ChangeLog
r231133 r231137 1 2018-04-28 Caio Lima <ticaiolima@gmail.com> 2 3 [ESNext][BigInt] Implement support for "*" operation 4 https://bugs.webkit.org/show_bug.cgi?id=183721 5 6 Reviewed by Saam Barati. 7 8 Added BigInt support into times binary operator into LLInt and on 9 JITOperations profiledMul and unprofiledMul. We are also replacing all 10 uses of int to unsigned when there is no negative values for 11 variables. 12 13 * dfg/DFGConstantFoldingPhase.cpp: 14 (JSC::DFG::ConstantFoldingPhase::foldConstants): 15 * jit/JITOperations.cpp: 16 * runtime/CommonSlowPaths.cpp: 17 (JSC::SLOW_PATH_DECL): 18 * runtime/JSBigInt.cpp: 19 (JSC::JSBigInt::JSBigInt): 20 (JSC::JSBigInt::allocationSize): 21 (JSC::JSBigInt::createWithLength): 22 (JSC::JSBigInt::toString): 23 (JSC::JSBigInt::multiply): 24 (JSC::JSBigInt::digitDiv): 25 (JSC::JSBigInt::internalMultiplyAdd): 26 (JSC::JSBigInt::multiplyAccumulate): 27 (JSC::JSBigInt::equals): 28 (JSC::JSBigInt::absoluteDivSmall): 29 (JSC::JSBigInt::calculateMaximumCharactersRequired): 30 (JSC::JSBigInt::toStringGeneric): 31 (JSC::JSBigInt::rightTrim): 32 (JSC::JSBigInt::allocateFor): 33 (JSC::JSBigInt::parseInt): 34 (JSC::JSBigInt::digit): 35 (JSC::JSBigInt::setDigit): 36 * runtime/JSBigInt.h: 37 * runtime/Operations.h: 38 (JSC::jsMul): 39 1 40 2018-04-28 Commit Queue <commit-queue@webkit.org> 2 41 -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r231133 r231137 147 147 148 148 // FIXME: Revisit this condition when introducing BigInt to JSC. 149 auto isNonString CellConstant = [] (JSValue value) {150 return value && value.isCell() && !value.isString() ;149 auto isNonStringOrBigIntCellConstant = [] (JSValue value) { 150 return value && value.isCell() && !value.isString() && !value.isBigInt(); 151 151 }; 152 152 153 if (isNonString CellConstant(child1Constant)) {153 if (isNonStringOrBigIntCellConstant(child1Constant)) { 154 154 node->convertToCompareEqPtr(m_graph.freezeStrong(child1Constant.asCell()), node->child2()); 155 155 changed = true; 156 } else if (isNonString CellConstant(child2Constant)) {156 } else if (isNonStringOrBigIntCellConstant(child2Constant)) { 157 157 node->convertToCompareEqPtr(m_graph.freezeStrong(child2Constant.asCell()), node->child1()); 158 158 changed = true; -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r231133 r231137 2555 2555 } 2556 2556 2557 ALWAYS_INLINE static EncodedJSValue unprofiledMul(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 2558 { 2559 auto scope = DECLARE_THROW_SCOPE(vm); 2557 ALWAYS_INLINE static EncodedJSValue unprofiledMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 2558 { 2560 2559 JSValue op1 = JSValue::decode(encodedOp1); 2561 2560 JSValue op2 = JSValue::decode(encodedOp2); 2562 2561 2563 double a = op1.toNumber(exec); 2564 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 2565 scope.release(); 2566 double b = op2.toNumber(exec); 2567 return JSValue::encode(jsNumber(a * b)); 2568 } 2569 2570 ALWAYS_INLINE static EncodedJSValue profiledMul(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true) 2571 { 2572 auto scope = DECLARE_THROW_SCOPE(vm); 2562 return JSValue::encode(jsMul(exec, op1, op2)); 2563 } 2564 2565 ALWAYS_INLINE static EncodedJSValue profiledMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true) 2566 { 2573 2567 JSValue op1 = JSValue::decode(encodedOp1); 2574 2568 JSValue op2 = JSValue::decode(encodedOp2); … … 2577 2571 arithProfile.observeLHSAndRHS(op1, op2); 2578 2572 2579 double a = op1.toNumber(exec); 2580 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 2581 double b = op2.toNumber(exec); 2582 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 2583 2584 JSValue result = jsNumber(a * b); 2573 JSValue result = jsMul(exec, op1, op2); 2585 2574 arithProfile.observeResult(result); 2586 2575 return JSValue::encode(result); … … 2592 2581 NativeCallFrameTracer tracer(vm, exec); 2593 2582 2594 return unprofiledMul( *vm,exec, encodedOp1, encodedOp2);2583 return unprofiledMul(exec, encodedOp1, encodedOp2); 2595 2584 } 2596 2585 … … 2600 2589 NativeCallFrameTracer tracer(vm, exec); 2601 2590 2602 return unprofiledMul( *vm,exec, encodedOp1, encodedOp2);2591 return unprofiledMul(exec, encodedOp1, encodedOp2); 2603 2592 } 2604 2593 … … 2617 2606 #endif 2618 2607 2619 return unprofiledMul( *vm,exec, encodedOp1, encodedOp2);2608 return unprofiledMul(exec, encodedOp1, encodedOp2); 2620 2609 } 2621 2610 … … 2626 2615 2627 2616 ASSERT(arithProfile); 2628 return profiledMul( *vm,exec, encodedOp1, encodedOp2, *arithProfile);2617 return profiledMul(exec, encodedOp1, encodedOp2, *arithProfile); 2629 2618 } 2630 2619 … … 2644 2633 #endif 2645 2634 2646 return profiledMul( *vm,exec, encodedOp1, encodedOp2, *arithProfile, false);2635 return profiledMul(exec, encodedOp1, encodedOp2, *arithProfile, false); 2647 2636 } 2648 2637 … … 2654 2643 ArithProfile* arithProfile = mulIC->arithProfile(); 2655 2644 ASSERT(arithProfile); 2656 return profiledMul( *vm,exec, encodedOp1, encodedOp2, *arithProfile);2645 return profiledMul(exec, encodedOp1, encodedOp2, *arithProfile); 2657 2646 } 2658 2647 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r231133 r231137 487 487 JSValue left = OP_C(2).jsValue(); 488 488 JSValue right = OP_C(3).jsValue(); 489 double a = left.toNumber(exec); 490 if (UNLIKELY(throwScope.exception())) 491 RETURN(JSValue()); 492 double b = right.toNumber(exec); 489 JSValue leftPrimitive = left.toPrimitive(exec, PreferNumber); 490 CHECK_EXCEPTION(); 491 JSValue rightPrimitive = right.toPrimitive(exec, PreferNumber); 492 CHECK_EXCEPTION(); 493 494 if (leftPrimitive.isBigInt() || rightPrimitive.isBigInt()) { 495 if (leftPrimitive.isBigInt() && rightPrimitive.isBigInt()) { 496 JSValue result(JSBigInt::multiply(exec, asBigInt(leftPrimitive), asBigInt(rightPrimitive))); 497 RETURN_WITH_PROFILING(result, { 498 updateArithProfileForBinaryArithOp(exec, pc, result, left, right); 499 }); 500 } 501 502 THROW(createTypeError(exec, "Invalid mix of BigInt and other type in multiplication.")); 503 } 504 505 double a = leftPrimitive.toNumber(exec); 506 CHECK_EXCEPTION(); 507 double b = rightPrimitive.toNumber(exec); 508 CHECK_EXCEPTION(); 493 509 JSValue result = jsNumber(a * b); 494 510 RETURN_WITH_PROFILING(result, { -
trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp
r231133 r231137 70 70 } 71 71 72 JSBigInt::JSBigInt(VM& vm, Structure* structure, intlength)72 JSBigInt::JSBigInt(VM& vm, Structure* structure, unsigned length) 73 73 : Base(vm, structure) 74 74 , m_length(length) … … 94 94 } 95 95 96 size_t JSBigInt::allocationSize( intlength)96 size_t JSBigInt::allocationSize(unsigned length) 97 97 { 98 98 size_t sizeWithPadding = WTF::roundUpToMultipleOf<sizeof(size_t)>(sizeof(JSBigInt)); … … 100 100 } 101 101 102 JSBigInt* JSBigInt::createWithLength(VM& vm, intlength)102 JSBigInt* JSBigInt::createWithLength(VM& vm, unsigned length) 103 103 { 104 104 JSBigInt* bigInt = new (NotNull, allocateCell<JSBigInt>(vm.heap, allocationSize(length))) JSBigInt(vm, vm.bigIntStructure.get(), length); … … 224 224 } 225 225 226 String JSBigInt::toString(ExecState& state, intradix)226 String JSBigInt::toString(ExecState& state, unsigned radix) 227 227 { 228 228 if (this->isZero()) … … 245 245 246 246 internalMultiplyAdd(this, factor, summand, length(), this); 247 } 248 249 JSBigInt* JSBigInt::multiply(ExecState* state, JSBigInt* x, JSBigInt* y) 250 { 251 VM& vm = state->vm(); 252 253 if (x->isZero()) 254 return x; 255 if (y->isZero()) 256 return y; 257 258 unsigned resultLength = x->length() + y->length(); 259 JSBigInt* result = JSBigInt::createWithLength(vm, resultLength); 260 result->initialize(InitializationType::WithZero); 261 262 for (unsigned i = 0; i < x->length(); i++) 263 multiplyAccumulate(y, x->digit(i), result, i); 264 265 result->setSign(x->sign() != y->sign()); 266 return result->rightTrim(vm); 247 267 } 248 268 … … 379 399 // Adapted from Warren, Hacker's Delight, p. 152. 380 400 #if USE(JSVALUE64) 381 ints = clz64(divisor);401 unsigned s = clz64(divisor); 382 402 #else 383 ints = clz32(divisor);403 unsigned s = clz32(divisor); 384 404 #endif 385 405 divisor <<= s; … … 424 444 // Multiplies {source} with {factor} and adds {summand} to the result. 425 445 // {result} and {source} may be the same BigInt for inplace modification. 426 void JSBigInt::internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, intn, JSBigInt* result)446 void JSBigInt::internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned n, JSBigInt* result) 427 447 { 428 448 ASSERT(source->length() >= n); … … 431 451 Digit carry = summand; 432 452 Digit high = 0; 433 for ( inti = 0; i < n; i++) {453 for (unsigned i = 0; i < n; i++) { 434 454 Digit current = source->digit(i); 435 455 Digit newCarry = 0; … … 459 479 } 460 480 481 // Multiplies {multiplicand} with {multiplier} and adds the result to 482 // {accumulator}, starting at {accumulatorIndex} for the least-significant 483 // digit. 484 // Callers must ensure that {accumulator} is big enough to hold the result. 485 void JSBigInt::multiplyAccumulate(JSBigInt* multiplicand, Digit multiplier, JSBigInt* accumulator, unsigned accumulatorIndex) 486 { 487 ASSERT(accumulator->length() > multiplicand->length() + accumulatorIndex); 488 if (!multiplier) 489 return; 490 491 Digit carry = 0; 492 Digit high = 0; 493 for (unsigned i = 0; i < multiplicand->length(); i++, accumulatorIndex++) { 494 Digit acc = accumulator->digit(accumulatorIndex); 495 Digit newCarry = 0; 496 497 // Add last round's carryovers. 498 acc = digitAdd(acc, high, newCarry); 499 acc = digitAdd(acc, carry, newCarry); 500 501 // Compute this round's multiplication. 502 Digit multiplicandDigit = multiplicand->digit(i); 503 Digit low = digitMul(multiplier, multiplicandDigit, high); 504 acc = digitAdd(acc, low, newCarry); 505 506 // Store result and prepare for next round. 507 accumulator->setDigit(accumulatorIndex, acc); 508 carry = newCarry; 509 } 510 511 while (carry || high) { 512 ASSERT(accumulatorIndex < accumulator->length()); 513 Digit acc = accumulator->digit(accumulatorIndex); 514 Digit newCarry = 0; 515 acc = digitAdd(acc, high, newCarry); 516 high = 0; 517 acc = digitAdd(acc, carry, newCarry); 518 accumulator->setDigit(accumulatorIndex, acc); 519 carry = newCarry; 520 accumulatorIndex++; 521 } 522 } 523 461 524 bool JSBigInt::equals(JSBigInt* x, JSBigInt* y) 462 525 { … … 467 530 return false; 468 531 469 for ( inti = 0; i < x->length(); i++) {532 for (unsigned i = 0; i < x->length(); i++) { 470 533 if (x->digit(i) != y->digit(i)) 471 534 return false; … … 495 558 } 496 559 497 intlength = x->length();560 unsigned length = x->length(); 498 561 if (quotient != nullptr) { 499 562 if (*quotient == nullptr) … … 522 585 }; 523 586 524 static const intbitsPerCharTableShift = 5;587 static const unsigned bitsPerCharTableShift = 5; 525 588 static const size_t bitsPerCharTableMultiplier = 1u << bitsPerCharTableShift; 526 589 527 590 // Compute (an overapproximation of) the length of the resulting string: 528 591 // Divide bit length of the BigInt by bits representable per character. 529 uint64_t JSBigInt::calculateMaximumCharactersRequired( int length, intradix, Digit lastDigit, bool sign)530 { 531 intleadingZeros;592 uint64_t JSBigInt::calculateMaximumCharactersRequired(unsigned length, unsigned radix, Digit lastDigit, bool sign) 593 { 594 unsigned leadingZeros; 532 595 if (sizeof(lastDigit) == 8) 533 596 leadingZeros = clz64(lastDigit); … … 557 620 } 558 621 559 String JSBigInt::toStringGeneric(ExecState& state, JSBigInt* x, intradix)622 String JSBigInt::toStringGeneric(ExecState& state, JSBigInt* x, unsigned radix) 560 623 { 561 624 // FIXME: [JSC] Revisit usage of StringVector into JSBigInt::toString … … 566 629 ASSERT(!x->isZero()); 567 630 568 intlength = x->length();631 unsigned length = x->length(); 569 632 bool sign = x->sign(); 570 633 … … 582 645 lastDigit = x->digit(0); 583 646 else { 584 intchunkChars = digitBits * bitsPerCharTableMultiplier / maxBitsPerChar;647 unsigned chunkChars = digitBits * bitsPerCharTableMultiplier / maxBitsPerChar; 585 648 Digit chunkDivisor = digitPow(radix, chunkChars); 586 649 587 650 // By construction of chunkChars, there can't have been overflow. 588 651 ASSERT(chunkDivisor); 589 intnonZeroDigit = length - 1;652 unsigned nonZeroDigit = length - 1; 590 653 ASSERT(x->digit(nonZeroDigit)); 591 654 … … 603 666 604 667 dividend = &rest; 605 for ( inti = 0; i < chunkChars; i++) {668 for (unsigned i = 0; i < chunkChars; i++) { 606 669 resultString.append(radixDigits[chunk % radix]); 607 670 chunk /= radix; … … 628 691 629 692 // Remove leading zeroes. 630 intnewSizeNoLeadingZeroes = resultString.size();693 unsigned newSizeNoLeadingZeroes = resultString.size(); 631 694 while (newSizeNoLeadingZeroes > 1 && resultString[newSizeNoLeadingZeroes - 1] == '0') 632 695 newSizeNoLeadingZeroes--; … … 646 709 if (isZero()) 647 710 return this; 711 712 ASSERT(m_length); 648 713 649 714 int nonZeroIndex = m_length - 1; … … 651 716 nonZeroIndex--; 652 717 653 if (nonZeroIndex == m_length - 1)718 if (nonZeroIndex == static_cast<int>(m_length - 1)) 654 719 return this; 655 720 656 intnewLength = nonZeroIndex + 1;721 unsigned newLength = nonZeroIndex + 1; 657 722 JSBigInt* trimmedBigInt = createWithLength(vm, newLength); 658 723 RELEASE_ASSERT(trimmedBigInt); … … 664 729 } 665 730 666 JSBigInt* JSBigInt::allocateFor(ExecState* state, VM& vm, int radix, intcharcount)731 JSBigInt* JSBigInt::allocateFor(ExecState* state, VM& vm, unsigned radix, unsigned charcount) 667 732 { 668 733 ASSERT(2 <= radix && radix <= 36); … … 671 736 size_t bitsPerChar = maxBitsPerCharTable[radix]; 672 737 size_t chars = charcount; 673 const introundup = bitsPerCharTableMultiplier - 1;738 const unsigned roundup = bitsPerCharTableMultiplier - 1; 674 739 if (chars <= (std::numeric_limits<size_t>::max() - roundup) / bitsPerChar) { 675 740 size_t bitsMin = bitsPerChar * chars; … … 679 744 if (bitsMin <= static_cast<size_t>(maxInt)) { 680 745 // Divide by kDigitsBits, rounding up. 681 int length = (static_cast<int>(bitsMin)+ digitBits - 1) / digitBits;746 unsigned length = (bitsMin + digitBits - 1) / digitBits; 682 747 if (length <= maxLength) { 683 748 JSBigInt* result = JSBigInt::createWithLength(vm, length); … … 720 785 721 786 template <typename CharType> 722 JSBigInt* JSBigInt::parseInt(ExecState* state, CharType* data, intlength)787 JSBigInt* JSBigInt::parseInt(ExecState* state, CharType* data, unsigned length) 723 788 { 724 789 VM& vm = state->vm(); 725 790 726 intp = 0;791 unsigned p = 0; 727 792 while (p < length && isStrWhiteSpace(data[p])) 728 793 ++p; … … 759 824 760 825 template <typename CharType> 761 JSBigInt* JSBigInt::parseInt(ExecState* state, VM& vm, CharType* data, int length, int startIndex, intradix, bool allowEmptyString)826 JSBigInt* JSBigInt::parseInt(ExecState* state, VM& vm, CharType* data, unsigned length, unsigned startIndex, unsigned radix, bool allowEmptyString) 762 827 { 763 828 ASSERT(length >= 0); 764 intp = startIndex;829 unsigned p = startIndex; 765 830 766 831 auto scope = DECLARE_THROW_SCOPE(vm); … … 778 843 int endIndex = length - 1; 779 844 // Removing trailing spaces 780 while (endIndex >= p&& isStrWhiteSpace(data[endIndex]))845 while (endIndex >= static_cast<int>(p) && isStrWhiteSpace(data[endIndex])) 781 846 --endIndex; 782 847 … … 786 851 return createZero(vm); 787 852 788 intlimit0 = '0' + (radix < 10 ? radix : 10);789 intlimita = 'a' + (radix - 10);790 intlimitA = 'A' + (radix - 10);853 unsigned limit0 = '0' + (radix < 10 ? radix : 10); 854 unsigned limita = 'a' + (radix - 10); 855 unsigned limitA = 'A' + (radix - 10); 791 856 792 857 JSBigInt* result = allocateFor(state, vm, radix, length - p); … … 795 860 result->initialize(InitializationType::WithZero); 796 861 797 for ( inti = p; i < length; i++, p++) {862 for (unsigned i = p; i < length; i++, p++) { 798 863 uint32_t digit; 799 864 if (data[i] >= '0' && data[i] < limit0) … … 823 888 } 824 889 825 JSBigInt::Digit JSBigInt::digit( intn)890 JSBigInt::Digit JSBigInt::digit(unsigned n) 826 891 { 827 892 ASSERT(n >= 0 && n < length()); … … 829 894 } 830 895 831 void JSBigInt::setDigit( intn, Digit value)896 void JSBigInt::setDigit(unsigned n, Digit value) 832 897 { 833 898 ASSERT(n >= 0 && n < length()); -
trunk/Source/JavaScriptCore/runtime/JSBigInt.h
r231133 r231137 42 42 public: 43 43 44 JSBigInt(VM&, Structure*, intlength);44 JSBigInt(VM&, Structure*, unsigned length); 45 45 46 46 enum class InitializationType { None, WithZero }; … … 50 50 51 51 static size_t estimatedSize(JSCell*); 52 static size_t allocationSize( intlength);52 static size_t allocationSize(unsigned length); 53 53 54 54 static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); 55 56 55 static JSBigInt* createZero(VM&); 57 static JSBigInt* createWithLength(VM&, intlength);56 static JSBigInt* createWithLength(VM&, unsigned length); 58 57 59 58 static JSBigInt* createFrom(VM&, int32_t value); … … 71 70 bool sign() const { return m_sign; } 72 71 73 void setLength( intlength) { m_length = length; }74 intlength() const { return m_length; }72 void setLength(unsigned length) { m_length = length; } 73 unsigned length() const { return m_length; } 75 74 76 75 static JSBigInt* parseInt(ExecState*, VM&, StringView, uint8_t radix); … … 78 77 79 78 std::optional<uint8_t> singleDigitValueForString(); 80 String toString(ExecState&, intradix);79 String toString(ExecState&, unsigned radix); 81 80 82 81 JS_EXPORT_PRIVATE static bool equals(JSBigInt*, JSBigInt*); … … 86 85 87 86 JSObject* toObject(ExecState*, JSGlobalObject*) const; 87 88 static JSBigInt* multiply(ExecState*, JSBigInt* x, JSBigInt* y); 88 89 89 90 private: 90 91 using Digit = uintptr_t; 91 static constexpr const intbitsPerByte = 8;92 static constexpr const intdigitBits = sizeof(Digit) * bitsPerByte;93 static constexpr const inthalfDigitBits = digitBits / 2;92 static constexpr const unsigned bitsPerByte = 8; 93 static constexpr const unsigned digitBits = sizeof(Digit) * bitsPerByte; 94 static constexpr const unsigned halfDigitBits = digitBits / 2; 94 95 static constexpr const Digit halfDigitMask = (1ull << halfDigitBits) - 1; 95 96 static constexpr const int maxInt = 0x7FFFFFFF; … … 99 100 // raising it later is easier than lowering it. 100 101 // Support up to 1 million bits. 101 static const intmaxLength = 1024 * 1024 / (sizeof(void*) * bitsPerByte);102 static const unsigned maxLength = 1024 * 1024 / (sizeof(void*) * bitsPerByte); 102 103 103 static uint64_t calculateMaximumCharactersRequired( int length, intradix, Digit lastDigit, bool sign);104 static uint64_t calculateMaximumCharactersRequired(unsigned length, unsigned radix, Digit lastDigit, bool sign); 104 105 105 106 static void absoluteDivSmall(ExecState&, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder); 106 static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, int, JSBigInt* result); 107 static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned, JSBigInt* result); 108 static void multiplyAccumulate(JSBigInt* multiplicand, Digit multiplier, JSBigInt* accumulator, unsigned accumulatorIndex); 107 109 108 110 // Digit arithmetic helpers. … … 113 115 static Digit digitPow(Digit base, Digit exponent); 114 116 115 static String toStringGeneric(ExecState&, JSBigInt*, intradix);117 static String toStringGeneric(ExecState&, JSBigInt*, unsigned radix); 116 118 117 119 bool isZero(); 118 120 119 121 template <typename CharType> 120 static JSBigInt* parseInt(ExecState*, CharType* data, intlength);122 static JSBigInt* parseInt(ExecState*, CharType* data, unsigned length); 121 123 122 124 template <typename CharType> 123 static JSBigInt* parseInt(ExecState*, VM&, CharType* data, int length, int startIndex, intradix, bool allowEmptyString = true);125 static JSBigInt* parseInt(ExecState*, VM&, CharType* data, unsigned length, unsigned startIndex, unsigned radix, bool allowEmptyString = true); 124 126 125 static JSBigInt* allocateFor(ExecState*, VM&, int radix, intcharcount);127 static JSBigInt* allocateFor(ExecState*, VM&, unsigned radix, unsigned charcount); 126 128 127 129 JSBigInt* rightTrim(VM&); … … 132 134 Digit* dataStorage(); 133 135 134 Digit digit( int);135 void setDigit( int, Digit);136 Digit digit(unsigned); 137 void setDigit(unsigned, Digit); 136 138 137 intm_length;139 unsigned m_length; 138 140 bool m_sign; 139 141 }; -
trunk/Source/JavaScriptCore/runtime/Operations.h
r231133 r231137 24 24 #include "CallFrame.h" 25 25 #include "ExceptionHelpers.h" 26 #include "JSBigInt.h" 26 27 #include "JSCJSValue.h" 27 28 … … 257 258 } 258 259 260 ALWAYS_INLINE JSValue jsMul(ExecState* state, JSValue v1, JSValue v2) 261 { 262 VM& vm = state->vm(); 263 auto scope = DECLARE_THROW_SCOPE(vm); 264 265 JSValue leftNumber = v1.toPrimitive(state, PreferNumber); 266 RETURN_IF_EXCEPTION(scope, { }); 267 JSValue rightNumber = v2.toPrimitive(state, PreferNumber); 268 RETURN_IF_EXCEPTION(scope, { }); 269 270 if (leftNumber.isBigInt() || rightNumber.isBigInt()) { 271 if (leftNumber.isBigInt() && rightNumber.isBigInt()) 272 return JSBigInt::multiply(state, asBigInt(leftNumber), asBigInt(rightNumber)); 273 274 throwTypeError(state, scope, ASCIILiteral("Invalid mix of BigInt and other type in multiplication.")); 275 return { }; 276 } 277 278 double leftValue = leftNumber.toNumber(state); 279 RETURN_IF_EXCEPTION(scope, { }); 280 double rightValue = rightNumber.toNumber(state); 281 RETURN_IF_EXCEPTION(scope, { }); 282 return jsNumber(leftValue * rightValue); 283 } 284 259 285 inline bool scribbleFreeCells() 260 286 {
Note: See TracChangeset
for help on using the changeset viewer.