Changeset 231845 in webkit


Ignore:
Timestamp:
May 16, 2018 7:26:30 AM (6 years ago)
Author:
Caio Lima
Message:

[ESNext][BigInt] Implement support for "/" operation
https://bugs.webkit.org/show_bug.cgi?id=183996

Reviewed by Yusuke Suzuki.

JSTests:

  • bigIntTests.yaml:
  • stress/big-int-div-jit.js: Added.
  • stress/big-int-div-memory-stress.js: Added.
  • stress/big-int-div-to-primitive-precedence.js: Added.
  • stress/big-int-div-to-primitive.js: Added.
  • stress/big-int-div-type-error.js: Added.
  • stress/big-int-div-wrapped-value.js: Added.
  • stress/big-int-division.js: Added.

Source/JavaScriptCore:

This patch is introducing the support for BigInt into divide
operation int LLInt and JIT layers.

  • dfg/DFGOperations.cpp:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/JSBigInt.cpp:

(JSC::JSBigInt::divide):
(JSC::JSBigInt::copy):
(JSC::JSBigInt::unaryMinus):
(JSC::JSBigInt::absoluteCompare):
(JSC::JSBigInt::absoluteDivLarge):
(JSC::JSBigInt::productGreaterThan):
(JSC::JSBigInt::inplaceAdd):
(JSC::JSBigInt::inplaceSub):
(JSC::JSBigInt::inplaceRightShift):
(JSC::JSBigInt::specialLeftShift):
(JSC::JSBigInt::digit):
(JSC::JSBigInt::setDigit):

  • runtime/JSBigInt.h:
Location:
trunk
Files:
6 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r231764 r231845  
     12018-05-16  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [ESNext][BigInt] Implement support for "/" operation
     4        https://bugs.webkit.org/show_bug.cgi?id=183996
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * bigIntTests.yaml:
     9        * stress/big-int-div-jit.js: Added.
     10        * stress/big-int-div-memory-stress.js: Added.
     11        * stress/big-int-div-to-primitive-precedence.js: Added.
     12        * stress/big-int-div-to-primitive.js: Added.
     13        * stress/big-int-div-type-error.js: Added.
     14        * stress/big-int-div-wrapped-value.js: Added.
     15        * stress/big-int-division.js: Added.
     16
    1172018-05-14  Leo Balter  <leonardo.balter@gmail.com>
    218
  • trunk/JSTests/bigIntTests.yaml

    r231733 r231845  
    119119  cmd: runBigIntEnabled
    120120
     121- path: stress/big-int-div-jit.js
     122  cmd: runBigIntEnabled
     123
     124- path: stress/big-int-div-memory-stress.js
     125  cmd: runBigIntEnabled
     126
     127- path: stress/big-int-div-to-primitive.js
     128  cmd: runBigIntEnabled
     129
     130- path: stress/big-int-div-type-error.js
     131  cmd: runBigIntEnabled
     132
     133- path: stress/big-int-div-wrapped-value.js
     134  cmd: runBigIntEnabled
     135
     136- path: stress/big-int-division.js
     137  cmd: runBigIntEnabled
  • trunk/Source/JavaScriptCore/ChangeLog

    r231843 r231845  
     12018-05-16  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [ESNext][BigInt] Implement support for "/" operation
     4        https://bugs.webkit.org/show_bug.cgi?id=183996
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        This patch is introducing the support for BigInt into divide
     9        operation int LLInt and JIT layers.
     10
     11        * dfg/DFGOperations.cpp:
     12        * runtime/CommonSlowPaths.cpp:
     13        (JSC::SLOW_PATH_DECL):
     14        * runtime/JSBigInt.cpp:
     15        (JSC::JSBigInt::divide):
     16        (JSC::JSBigInt::copy):
     17        (JSC::JSBigInt::unaryMinus):
     18        (JSC::JSBigInt::absoluteCompare):
     19        (JSC::JSBigInt::absoluteDivLarge):
     20        (JSC::JSBigInt::productGreaterThan):
     21        (JSC::JSBigInt::inplaceAdd):
     22        (JSC::JSBigInt::inplaceSub):
     23        (JSC::JSBigInt::inplaceRightShift):
     24        (JSC::JSBigInt::specialLeftShift):
     25        (JSC::JSBigInt::digit):
     26        (JSC::JSBigInt::setDigit):
     27        * runtime/JSBigInt.h:
     28
    1292018-05-16  Alberto Garcia  <berto@igalia.com>
    230
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r231839 r231845  
    7676#include "VMInlines.h"
    7777#include <wtf/InlineASM.h>
     78#include <wtf/Variant.h>
    7879
    7980#if ENABLE(JIT)
     
    425426    JSValue op2 = JSValue::decode(encodedOp2);
    426427
    427     double a = op1.toNumber(exec);
     428    auto leftNumeric = op1.toNumeric(exec);
    428429    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     430    auto rightNumeric = op2.toNumeric(exec);
     431    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     432
     433    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
     434        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
     435            JSBigInt* result = JSBigInt::divide(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     436            RETURN_IF_EXCEPTION(scope, encodedJSValue());
     437            return JSValue::encode(result);
     438        }
     439
     440        return throwVMTypeError(exec, scope, "Invalid operand in BigInt operation.");
     441    }
     442
    429443    scope.release();
    430     double b = op2.toNumber(exec);
     444
     445    double a = WTF::get<double>(leftNumeric);
     446    double b = WTF::get<double>(rightNumeric);
    431447    return JSValue::encode(jsNumber(a / b));
    432448}
  • trunk/Source/JavaScriptCore/runtime/BigIntPrototype.cpp

    r228500 r231845  
    104104    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    105105
    106     String resultString = value->toString(*state, radix);
     106    String resultString = value->toString(state, radix);
    107107    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    108108    scope.release();
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r231733 r231845  
    517517    JSValue left = OP_C(2).jsValue();
    518518    JSValue right = OP_C(3).jsValue();
    519     double a = left.toNumber(exec);
    520     if (UNLIKELY(throwScope.exception()))
    521         RETURN(JSValue());
    522     double b = right.toNumber(exec);
    523     if (UNLIKELY(throwScope.exception()))
    524         RETURN(JSValue());
     519    auto leftNumeric = left.toNumeric(exec);
     520    CHECK_EXCEPTION();
     521    auto rightNumeric = right.toNumeric(exec);
     522    CHECK_EXCEPTION();
     523
     524    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
     525        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
     526            JSValue result(JSBigInt::divide(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)));
     527            CHECK_EXCEPTION();
     528            RETURN_WITH_PROFILING(result, {
     529                updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
     530            });
     531        }
     532
     533        THROW(createTypeError(exec, "Invalid mix of BigInt and other type in division."));
     534    }
     535
     536    double a = WTF::get<double>(leftNumeric);
     537    double b = WTF::get<double>(rightNumeric);
    525538    JSValue result = jsNumber(a / b);
    526539    RETURN_WITH_PROFILING(result, {
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp

    r231733 r231845  
    228228}
    229229
    230 String JSBigInt::toString(ExecState& state, unsigned radix)
     230String JSBigInt::toString(ExecState* state, unsigned radix)
    231231{
    232232    if (this->isZero())
    233         return state.vm().smallStrings.singleCharacterStringRep('0');
     233        return state->vm().smallStrings.singleCharacterStringRep('0');
    234234
    235235    return toStringGeneric(state, this, radix);
     
    269269    result->setSign(x->sign() != y->sign());
    270270    return result->rightTrim(vm);
     271}
     272
     273JSBigInt* JSBigInt::divide(ExecState* state, JSBigInt* x, JSBigInt* y)
     274{
     275    // 1. If y is 0n, throw a RangeError exception.
     276    VM& vm = state->vm();
     277    auto scope = DECLARE_THROW_SCOPE(vm);
     278
     279    if (y->isZero()) {
     280        throwRangeError(state, scope, ASCIILiteral("0 is an invalid divisor value."));
     281        return nullptr;
     282    }
     283
     284    // 2. Let quotient be the mathematical value of x divided by y.
     285    // 3. Return a BigInt representing quotient rounded towards 0 to the next
     286    //    integral value.
     287    if (absoluteCompare(x, y) == ComparisonResult::LessThan)
     288        return createZero(vm);
     289
     290    JSBigInt* quotient = nullptr;
     291    bool resultSign = x->sign() != y->sign();
     292    if (y->length() == 1) {
     293        Digit divisor = y->digit(0);
     294        if (divisor == 1)
     295            return resultSign == x->sign() ? x : unaryMinus(vm, x);
     296
     297        Digit remainder;
     298        absoluteDivWithDigitDivisor(vm, x, divisor, &quotient, remainder);
     299    } else
     300        absoluteDivWithBigIntDivisor(vm, x, y, &quotient, nullptr);
     301
     302    quotient->setSign(resultSign);
     303    return quotient->rightTrim(vm);
     304}
     305
     306JSBigInt* JSBigInt::copy(VM& vm, JSBigInt* x)
     307{
     308    ASSERT(!x->isZero());
     309
     310    JSBigInt* result = JSBigInt::createWithLength(vm, x->length());
     311    std::copy(x->dataStorage(), x->dataStorage() + x->length(), result->dataStorage());
     312    result->setSign(x->sign());
     313    return result;
     314}
     315
     316JSBigInt* JSBigInt::unaryMinus(VM& vm, JSBigInt* x)
     317{
     318    if (x->isZero())
     319        return x;
     320
     321    JSBigInt* result = copy(vm, x);
     322    result->setSign(!x->sign());
     323    return result;
    271324}
    272325
     
    523576}
    524577
     578inline JSBigInt::ComparisonResult JSBigInt::absoluteCompare(JSBigInt* x, JSBigInt* y)
     579{
     580    ASSERT(!x->length() || x->digit(0));
     581    ASSERT(!y->length() || y->digit(0));
     582
     583    int diff = x->length() - y->length();
     584    if (diff)
     585        return diff < 0 ? ComparisonResult::LessThan : ComparisonResult::GreaterThan;
     586
     587    int i = x->length() - 1;
     588    while (i >= 0 && x->digit(i) == y->digit(i))
     589        i--;
     590
     591    if (i < 0)
     592        return ComparisonResult::Equal;
     593
     594    return x->digit(i) > y->digit(i) ? ComparisonResult::GreaterThan : ComparisonResult::LessThan;
     595}
     596
    525597// Divides {x} by {divisor}, returning the result in {quotient} and {remainder}.
    526598// Mathematically, the contract is:
     
    530602// {quotient} can be the same as {x} for an in-place division. {quotient} can
    531603// also be nullptr if the caller is only interested in the remainder.
    532 void JSBigInt::absoluteDivSmall(ExecState& state, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder)
     604void JSBigInt::absoluteDivWithDigitDivisor(VM& vm, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder)
    533605{
    534606    ASSERT(divisor);
    535607
    536     VM& vm = state.vm();
    537608    ASSERT(!x->isZero());
    538609    remainder = 0;
     
    556627            digitDiv(remainder, x->digit(i), divisor, remainder);
    557628    }
     629}
     630
     631// Divides {dividend} by {divisor}, returning the result in {quotient} and
     632// {remainder}. Mathematically, the contract is:
     633// quotient = (dividend - remainder) / divisor, with 0 <= remainder < divisor.
     634// Both {quotient} and {remainder} are optional, for callers that are only
     635// interested in one of them.
     636// See Knuth, Volume 2, section 4.3.1, Algorithm D.
     637void JSBigInt::absoluteDivWithBigIntDivisor(VM& vm, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder)
     638{
     639    ASSERT(divisor->length() >= 2);
     640    ASSERT(dividend->length() >= divisor->length());
     641
     642    // The unusual variable names inside this function are consistent with
     643    // Knuth's book, as well as with Go's implementation of this algorithm.
     644    // Maintaining this consistency is probably more useful than trying to
     645    // come up with more descriptive names for them.
     646    unsigned n = divisor->length();
     647    unsigned m = dividend->length() - n;
     648   
     649    // The quotient to be computed.
     650    JSBigInt* q = nullptr;
     651    if (quotient != nullptr)
     652        q = createWithLength(vm, m + 1);
     653   
     654    // In each iteration, {qhatv} holds {divisor} * {current quotient digit}.
     655    // "v" is the book's name for {divisor}, "qhat" the current quotient digit.
     656    JSBigInt* qhatv = createWithLength(vm, m + 1);
     657   
     658    // D1.
     659    // Left-shift inputs so that the divisor's MSB is set. This is necessary
     660    // to prevent the digit-wise divisions (see digit_div call below) from
     661    // overflowing (they take a two digits wide input, and return a one digit
     662    // result).
     663    Digit lastDigit = divisor->digit(n - 1);
     664    unsigned shift = sizeof(lastDigit) == 8 ? clz64(lastDigit) : clz32(lastDigit);
     665
     666    if (shift > 0)
     667        divisor = absoluteLeftShiftAlwaysCopy(vm, divisor, shift, LeftShiftMode::SameSizeResult);
     668
     669    // Holds the (continuously updated) remaining part of the dividend, which
     670    // eventually becomes the remainder.
     671    JSBigInt* u = absoluteLeftShiftAlwaysCopy(vm, dividend, shift, LeftShiftMode::AlwaysAddOneDigit);
     672
     673    // D2.
     674    // Iterate over the dividend's digit (like the "grad school" algorithm).
     675    // {vn1} is the divisor's most significant digit.
     676    Digit vn1 = divisor->digit(n - 1);
     677    for (int j = m; j >= 0; j--) {
     678        // D3.
     679        // Estimate the current iteration's quotient digit (see Knuth for details).
     680        // {qhat} is the current quotient digit.
     681        Digit qhat = std::numeric_limits<Digit>::max();
     682
     683        // {ujn} is the dividend's most significant remaining digit.
     684        Digit ujn = u->digit(j + n);
     685        if (ujn != vn1) {
     686            // {rhat} is the current iteration's remainder.
     687            Digit rhat = 0;
     688            // Estimate the current quotient digit by dividing the most significant
     689            // digits of dividend and divisor. The result will not be too small,
     690            // but could be a bit too large.
     691            qhat = digitDiv(ujn, u->digit(j + n - 1), vn1, rhat);
     692           
     693            // Decrement the quotient estimate as needed by looking at the next
     694            // digit, i.e. by testing whether
     695            // qhat * v_{n-2} > (rhat << digitBits) + u_{j+n-2}.
     696            Digit vn2 = divisor->digit(n - 2);
     697            Digit ujn2 = u->digit(j + n - 2);
     698            while (productGreaterThan(qhat, vn2, rhat, ujn2)) {
     699                qhat--;
     700                Digit prevRhat = rhat;
     701                rhat += vn1;
     702                // v[n-1] >= 0, so this tests for overflow.
     703                if (rhat < prevRhat)
     704                    break;
     705            }
     706        }
     707
     708        // D4.
     709        // Multiply the divisor with the current quotient digit, and subtract
     710        // it from the dividend. If there was "borrow", then the quotient digit
     711        // was one too high, so we must correct it and undo one subtraction of
     712        // the (shifted) divisor.
     713        internalMultiplyAdd(divisor, qhat, 0, n, qhatv);
     714        Digit c = u->absoluteInplaceSub(qhatv, j);
     715        if (c) {
     716            c = u->absoluteInplaceAdd(divisor, j);
     717            u->setDigit(j + n, u->digit(j + n) + c);
     718            qhat--;
     719        }
     720       
     721        if (quotient != nullptr)
     722            q->setDigit(j, qhat);
     723    }
     724
     725    if (quotient != nullptr) {
     726        // Caller will right-trim.
     727        *quotient = q;
     728    }
     729
     730    if (remainder != nullptr) {
     731        u->inplaceRightShift(shift);
     732        *remainder = u;
     733    }
     734}
     735
     736// Returns whether (factor1 * factor2) > (high << kDigitBits) + low.
     737inline bool JSBigInt::productGreaterThan(Digit factor1, Digit factor2, Digit high, Digit low)
     738{
     739    Digit resultHigh;
     740    Digit resultLow = digitMul(factor1, factor2, resultHigh);
     741    return resultHigh > high || (resultHigh == high && resultLow > low);
     742}
     743
     744// Adds {summand} onto {this}, starting with {summand}'s 0th digit
     745// at {this}'s {startIndex}'th digit. Returns the "carry" (0 or 1).
     746JSBigInt::Digit JSBigInt::absoluteInplaceAdd(JSBigInt* summand, unsigned startIndex)
     747{
     748    Digit carry = 0;
     749    unsigned n = summand->length();
     750    ASSERT(length() >= startIndex + n);
     751    for (unsigned i = 0; i < n; i++) {
     752        Digit newCarry = 0;
     753        Digit sum = digitAdd(digit(startIndex + i), summand->digit(i), newCarry);
     754        sum = digitAdd(sum, carry, newCarry);
     755        setDigit(startIndex + i, sum);
     756        carry = newCarry;
     757    }
     758
     759    return carry;
     760}
     761
     762// Subtracts {subtrahend} from {this}, starting with {subtrahend}'s 0th digit
     763// at {this}'s {startIndex}-th digit. Returns the "borrow" (0 or 1).
     764JSBigInt::Digit JSBigInt::absoluteInplaceSub(JSBigInt* subtrahend, unsigned startIndex)
     765{
     766    Digit borrow = 0;
     767    unsigned n = subtrahend->length();
     768    ASSERT(length() >= startIndex + n);
     769    for (unsigned i = 0; i < n; i++) {
     770        Digit newBorrow = 0;
     771        Digit difference = digitSub(digit(startIndex + i), subtrahend->digit(i), newBorrow);
     772        difference = digitSub(difference, borrow, newBorrow);
     773        setDigit(startIndex + i, difference);
     774        borrow = newBorrow;
     775    }
     776
     777    return borrow;
     778}
     779
     780void JSBigInt::inplaceRightShift(unsigned shift)
     781{
     782    ASSERT(shift < digitBits);
     783    ASSERT(!(digit(0) & ((static_cast<Digit>(1) << shift) - 1)));
     784
     785    if (!shift)
     786        return;
     787
     788    Digit carry = digit(0) >> shift;
     789    unsigned last = length() - 1;
     790    for (unsigned i = 0; i < last; i++) {
     791        Digit d = digit(i + 1);
     792        setDigit(i, (d << (digitBits - shift)) | carry);
     793        carry = d >> shift;
     794    }
     795    setDigit(last, carry);
     796}
     797
     798// Always copies the input, even when {shift} == 0.
     799JSBigInt* JSBigInt::absoluteLeftShiftAlwaysCopy(VM& vm, JSBigInt* x, unsigned shift, LeftShiftMode mode)
     800{
     801    ASSERT(shift < digitBits);
     802    ASSERT(!x->isZero());
     803
     804    unsigned n = x->length();
     805    unsigned resultLength = mode == LeftShiftMode::AlwaysAddOneDigit ? n + 1 : n;
     806    JSBigInt* result = createWithLength(vm, resultLength);
     807
     808    if (!shift) {
     809        for (unsigned i = 0; i < n; i++)
     810            result->setDigit(i, x->digit(i));
     811        if (mode == LeftShiftMode::AlwaysAddOneDigit)
     812            result->setDigit(n, 0);
     813
     814        return result;
     815    }
     816
     817    Digit carry = 0;
     818    for (unsigned i = 0; i < n; i++) {
     819        Digit d = x->digit(i);
     820        result->setDigit(i, (d << shift) | carry);
     821        carry = d >> (digitBits - shift);
     822    }
     823
     824    if (mode == LeftShiftMode::AlwaysAddOneDigit)
     825        result->setDigit(n, carry);
     826    else {
     827        ASSERT(mode == LeftShiftMode::SameSizeResult);
     828        ASSERT(!carry);
     829    }
     830
     831    return result;
    558832}
    559833
     
    605879}
    606880
    607 String JSBigInt::toStringGeneric(ExecState& state, JSBigInt* x, unsigned radix)
     881String JSBigInt::toStringGeneric(ExecState* state, JSBigInt* x, unsigned radix)
    608882{
    609883    // FIXME: [JSC] Revisit usage of Vector into JSBigInt::toString
     
    611885    Vector<LChar> resultString;
    612886
     887    VM& vm = state->vm();
     888
    613889    ASSERT(radix >= 2 && radix <= 36);
    614890    ASSERT(!x->isZero());
     
    621897
    622898    if (maximumCharactersRequired > JSString::MaxLength) {
    623         auto scope = DECLARE_THROW_SCOPE(state.vm());
    624         throwOutOfMemoryError(&state, scope);
     899        auto scope = DECLARE_THROW_SCOPE(vm);
     900        throwOutOfMemoryError(state, scope);
    625901        return String();
    626902    }
     
    647923        do {
    648924            Digit chunk;
    649             absoluteDivSmall(state, *dividend, chunkDivisor, &rest, chunk);
     925            absoluteDivWithDigitDivisor(vm, *dividend, chunkDivisor, &rest, chunk);
    650926            ASSERT(rest);
    651927
     
    695971        return this;
    696972
    697     ASSERT(m_length);
    698 
    699     int nonZeroIndex = m_length - 1;
    700     while (nonZeroIndex >= 0 && !digit(nonZeroIndex))
     973    unsigned nonZeroIndex = m_length - 1;
     974    while (!digit(nonZeroIndex))
    701975        nonZeroIndex--;
    702976
    703     if (nonZeroIndex == static_cast<int>(m_length - 1))
     977    if (nonZeroIndex == m_length - 1)
    704978        return this;
    705979
     
    8751149}
    8761150
    877 JSBigInt::Digit JSBigInt::digit(unsigned n)
    878 {
    879     ASSERT(n >= 0 && n < length());
     1151inline JSBigInt::Digit JSBigInt::digit(unsigned n)
     1152{
     1153    ASSERT(n < length());
    8801154    return dataStorage()[n];
    8811155}
    8821156
    883 void JSBigInt::setDigit(unsigned n, Digit value)
    884 {
    885     ASSERT(n >= 0 && n < length());
     1157inline void JSBigInt::setDigit(unsigned n, Digit value)
     1158{
     1159    ASSERT(n < length());
    8861160    dataStorage()[n] = value;
    8871161}
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.h

    r231733 r231845  
    8383
    8484    std::optional<uint8_t> singleDigitValueForString();
    85     String toString(ExecState&, unsigned radix);
     85    String toString(ExecState*, unsigned radix);
    8686   
    8787    JS_EXPORT_PRIVATE static bool equals(JSBigInt*, JSBigInt*);
     
    9595    static JSBigInt* multiply(ExecState*, JSBigInt* x, JSBigInt* y);
    9696   
     97    static JSBigInt* divide(ExecState*, JSBigInt* x, JSBigInt* y);
     98    static JSBigInt* unaryMinus(VM&, JSBigInt* x);
     99   
    97100private:
    98101
    99     enum ComparisonResult {
     102    enum class ComparisonResult {
    100103        Equal,
    101104        Undefined,
     
    119122    static uint64_t calculateMaximumCharactersRequired(unsigned length, unsigned radix, Digit lastDigit, bool sign);
    120123   
    121     static void absoluteDivSmall(ExecState&, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder);
     124    static ComparisonResult absoluteCompare(JSBigInt* x, JSBigInt* y);
     125    static void absoluteDivWithDigitDivisor(VM&, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder);
    122126    static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned, JSBigInt* result);
    123127    static void multiplyAccumulate(JSBigInt* multiplicand, Digit multiplier, JSBigInt* accumulator, unsigned accumulatorIndex);
     128    static void absoluteDivWithBigIntDivisor(VM&, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder);
     129   
     130    enum class LeftShiftMode {
     131        SameSizeResult,
     132        AlwaysAddOneDigit
     133    };
     134   
     135    static JSBigInt* absoluteLeftShiftAlwaysCopy(VM&, JSBigInt* x, unsigned shift, LeftShiftMode);
     136    static bool productGreaterThan(Digit factor1, Digit factor2, Digit high, Digit low);
     137
     138    Digit absoluteInplaceAdd(JSBigInt* summand, unsigned startIndex);
     139    Digit absoluteInplaceSub(JSBigInt* subtrahend, unsigned startIndex);
     140    void inplaceRightShift(unsigned shift);
    124141
    125142    // Digit arithmetic helpers.
     
    130147    static Digit digitPow(Digit base, Digit exponent);
    131148
    132     static String toStringGeneric(ExecState&, JSBigInt*, unsigned radix);
     149    static String toStringGeneric(ExecState*, JSBigInt*, unsigned radix);
    133150
    134151    bool isZero();
     
    144161    static JSBigInt* allocateFor(ExecState*, VM&, unsigned radix, unsigned charcount);
    145162
     163    static JSBigInt* copy(VM&, JSBigInt* x);
    146164    JSBigInt* rightTrim(VM&);
    147165
  • trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp

    r229410 r231845  
    383383        if (auto digit = bigInt->singleDigitValueForString())
    384384            return vm.smallStrings.singleCharacterString(*digit + '0');
    385         JSString* returnString = jsNontrivialString(&vm, bigInt->toString(*exec, 10));
     385        JSString* returnString = jsNontrivialString(&vm, bigInt->toString(exec, 10));
    386386        RETURN_IF_EXCEPTION(scope, errorValue());
    387387        return returnString;
Note: See TracChangeset for help on using the changeset viewer.