Changeset 238132 in webkit


Ignore:
Timestamp:
Nov 13, 2018 7:46:34 AM (5 years ago)
Author:
Caio Lima
Message:

[BigInt] JSBigInt::createWithLength should throw when length is greater than JSBigInt::maxLength
https://bugs.webkit.org/show_bug.cgi?id=190836

Reviewed by Saam Barati.

JSTests:

  • stress/big-int-out-of-memory-tests.js: Added.

Source/JavaScriptCore:

In this patch we are creating a new method called JSBigInt::createWithLengthUnchecked
where we allocate a BigInt trusting the length received as argument.
With this additional method, we now check if length passed to
JSBigInt::createWithLength is not greater than JSBigInt::maxLength.
When the length is greater than maxLength, we then throw OOM
exception.
This required change the interface of some JSBigInt operations to
receive ExecState* instead of VM&. We changed only operations that
can throw because of OOM.
We beleive that this approach of throwing instead of finishing the
execution abruptly is better because JS programs can catch such
exception and handle this issue properly.

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

(JSC::SLOW_PATH_DECL):

  • runtime/JSBigInt.cpp:

(JSC::JSBigInt::createZero):
(JSC::JSBigInt::tryCreateWithLength):
(JSC::JSBigInt::createWithLengthUnchecked):
(JSC::JSBigInt::createFrom):
(JSC::JSBigInt::multiply):
(JSC::JSBigInt::divide):
(JSC::JSBigInt::copy):
(JSC::JSBigInt::unaryMinus):
(JSC::JSBigInt::remainder):
(JSC::JSBigInt::add):
(JSC::JSBigInt::sub):
(JSC::JSBigInt::bitwiseAnd):
(JSC::JSBigInt::bitwiseOr):
(JSC::JSBigInt::bitwiseXor):
(JSC::JSBigInt::absoluteAdd):
(JSC::JSBigInt::absoluteSub):
(JSC::JSBigInt::absoluteDivWithDigitDivisor):
(JSC::JSBigInt::absoluteDivWithBigIntDivisor):
(JSC::JSBigInt::absoluteLeftShiftAlwaysCopy):
(JSC::JSBigInt::absoluteBitwiseOp):
(JSC::JSBigInt::absoluteAddOne):
(JSC::JSBigInt::absoluteSubOne):
(JSC::JSBigInt::toStringGeneric):
(JSC::JSBigInt::rightTrim):
(JSC::JSBigInt::allocateFor):
(JSC::JSBigInt::createWithLength): Deleted.

  • runtime/JSBigInt.h:
  • runtime/Operations.cpp:

(JSC::jsAddSlowCase):

  • runtime/Operations.h:

(JSC::jsSub):
(JSC::jsMul):

Location:
trunk
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r238004 r238132  
     12018-11-13  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [BigInt] JSBigInt::createWithLength should throw when length is greater than JSBigInt::maxLength
     4        https://bugs.webkit.org/show_bug.cgi?id=190836
     5
     6        Reviewed by Saam Barati.
     7
     8        * stress/big-int-out-of-memory-tests.js: Added.
     9
    1102018-11-08  Ross Kirsling  <ross.kirsling@sony.com>
    211
  • trunk/Source/JavaScriptCore/ChangeLog

    r238122 r238132  
     12018-11-13  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [BigInt] JSBigInt::createWithLength should throw when length is greater than JSBigInt::maxLength
     4        https://bugs.webkit.org/show_bug.cgi?id=190836
     5
     6        Reviewed by Saam Barati.
     7
     8        In this patch we are creating a new method called `JSBigInt::createWithLengthUnchecked`
     9        where we allocate a BigInt trusting the length received as argument.
     10        With this additional method, we now check if length passed to
     11        `JSBigInt::createWithLength` is not greater than JSBigInt::maxLength.
     12        When the length is greater than maxLength, we then throw OOM
     13        exception.
     14        This required change the interface of some JSBigInt operations to
     15        receive `ExecState*` instead of `VM&`. We changed only operations that
     16        can throw because of OOM.
     17        We beleive that this approach of throwing instead of finishing the
     18        execution abruptly is better because JS programs can catch such
     19        exception and handle this issue properly.
     20
     21        * dfg/DFGOperations.cpp:
     22        * jit/JITOperations.cpp:
     23        * runtime/CommonSlowPaths.cpp:
     24        (JSC::SLOW_PATH_DECL):
     25        * runtime/JSBigInt.cpp:
     26        (JSC::JSBigInt::createZero):
     27        (JSC::JSBigInt::tryCreateWithLength):
     28        (JSC::JSBigInt::createWithLengthUnchecked):
     29        (JSC::JSBigInt::createFrom):
     30        (JSC::JSBigInt::multiply):
     31        (JSC::JSBigInt::divide):
     32        (JSC::JSBigInt::copy):
     33        (JSC::JSBigInt::unaryMinus):
     34        (JSC::JSBigInt::remainder):
     35        (JSC::JSBigInt::add):
     36        (JSC::JSBigInt::sub):
     37        (JSC::JSBigInt::bitwiseAnd):
     38        (JSC::JSBigInt::bitwiseOr):
     39        (JSC::JSBigInt::bitwiseXor):
     40        (JSC::JSBigInt::absoluteAdd):
     41        (JSC::JSBigInt::absoluteSub):
     42        (JSC::JSBigInt::absoluteDivWithDigitDivisor):
     43        (JSC::JSBigInt::absoluteDivWithBigIntDivisor):
     44        (JSC::JSBigInt::absoluteLeftShiftAlwaysCopy):
     45        (JSC::JSBigInt::absoluteBitwiseOp):
     46        (JSC::JSBigInt::absoluteAddOne):
     47        (JSC::JSBigInt::absoluteSubOne):
     48        (JSC::JSBigInt::toStringGeneric):
     49        (JSC::JSBigInt::rightTrim):
     50        (JSC::JSBigInt::allocateFor):
     51        (JSC::JSBigInt::createWithLength): Deleted.
     52        * runtime/JSBigInt.h:
     53        * runtime/Operations.cpp:
     54        (JSC::jsAddSlowCase):
     55        * runtime/Operations.h:
     56        (JSC::jsSub):
     57        (JSC::jsMul):
     58
    1592018-11-12  Devin Rousso  <drousso@apple.com>
    260
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r237972 r238132  
    350350    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    351351        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    352             JSBigInt* result = JSBigInt::bitwiseAnd(*vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     352            JSBigInt* result = JSBigInt::bitwiseAnd(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
    353353            RETURN_IF_EXCEPTION(scope, encodedJSValue());
    354354            return JSValue::encode(result);
     
    377377    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    378378        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    379             JSBigInt* result = JSBigInt::bitwiseOr(*vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     379            JSBigInt* result = JSBigInt::bitwiseOr(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
    380380            RETURN_IF_EXCEPTION(scope, encodedJSValue());
    381381            return JSValue::encode(result);
     
    12951295    JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
    12961296   
    1297     return JSBigInt::sub(*vm, leftOperand, rightOperand);
     1297    return JSBigInt::sub(exec, leftOperand, rightOperand);
    12981298}
    12991299
     
    13061306    JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
    13071307
    1308     return JSBigInt::bitwiseAnd(*vm, leftOperand, rightOperand);
     1308    return JSBigInt::bitwiseAnd(exec, leftOperand, rightOperand);
    13091309}
    13101310
     
    13171317    JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
    13181318   
    1319     return JSBigInt::add(*vm, leftOperand, rightOperand);
     1319    return JSBigInt::add(exec, leftOperand, rightOperand);
    13201320}
    13211321
     
    13281328    JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
    13291329   
    1330     return JSBigInt::bitwiseOr(*vm, leftOperand, rightOperand);
     1330    return JSBigInt::bitwiseOr(exec, leftOperand, rightOperand);
    13311331}
    13321332
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r237547 r238132  
    27672767    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    27682768   
    2769     if (primValue.isBigInt()) {
    2770         JSBigInt* result = JSBigInt::unaryMinus(vm, asBigInt(primValue));
    2771         return JSValue::encode(result);
    2772     }
     2769    if (primValue.isBigInt())
     2770        return JSValue::encode(JSBigInt::unaryMinus(vm, asBigInt(primValue)));
    27732771
    27742772    double number = primValue.toNumber(exec);
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r237972 r238132  
    564564    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    565565        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    566             JSBigInt* result = JSBigInt::sub(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     566            JSBigInt* result = JSBigInt::sub(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     567            CHECK_EXCEPTION();
    567568            RETURN_WITH_PROFILING(result, {
    568569                updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
     
    700701    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    701702        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    702             JSBigInt* result = JSBigInt::bitwiseAnd(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     703            JSBigInt* result = JSBigInt::bitwiseAnd(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
    703704            CHECK_EXCEPTION();
    704705            RETURN_PROFILED(result);
     
    721722    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    722723        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    723             JSBigInt* result = JSBigInt::bitwiseOr(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     724            JSBigInt* result = JSBigInt::bitwiseOr(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
    724725            CHECK_EXCEPTION();
    725726            RETURN_PROFILED(result);
     
    742743    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    743744        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    744             JSBigInt* result = JSBigInt::bitwiseXor(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     745            JSBigInt* result = JSBigInt::bitwiseXor(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
    745746            CHECK_EXCEPTION();
    746747            RETURN(result);
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp

    r237296 r238132  
    8282JSBigInt* JSBigInt::createZero(VM& vm)
    8383{
    84     JSBigInt* zeroBigInt = createWithLength(vm, 0);
     84    JSBigInt* zeroBigInt = createWithLengthUnchecked(vm, 0);
    8585    return zeroBigInt;
    8686}
     
    9292}
    9393
    94 JSBigInt* JSBigInt::createWithLength(VM& vm, unsigned length)
     94JSBigInt* JSBigInt::tryCreateWithLength(ExecState* exec, unsigned length)
     95{
     96    VM& vm = exec->vm();
     97    auto scope = DECLARE_THROW_SCOPE(vm);
     98
     99    if (UNLIKELY(length > maxLength)) {
     100        throwOutOfMemoryError(exec, scope);
     101        return nullptr;
     102    }
     103
     104    scope.release();
     105
     106    return createWithLengthUnchecked(vm, length);
     107}
     108
     109JSBigInt* JSBigInt::createWithLengthUnchecked(VM& vm, unsigned length)
    95110{
    96111    JSBigInt* bigInt = new (NotNull, allocateCell<JSBigInt>(vm.heap, allocationSize(length))) JSBigInt(vm, vm.bigIntStructure.get(), length);
     
    104119        return createZero(vm);
    105120   
    106     JSBigInt* bigInt = createWithLength(vm, 1);
    107    
     121    JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
    108122    if (value < 0) {
    109123        bigInt->setDigit(0, static_cast<Digit>(-1 * static_cast<int64_t>(value)));
     
    120134        return createZero(vm);
    121135   
    122     JSBigInt* bigInt = createWithLength(vm, 1);
     136    JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
    123137    bigInt->setDigit(0, static_cast<Digit>(value));
    124138    return bigInt;
     
    131145   
    132146    if (sizeof(Digit) == 8) {
    133         JSBigInt* bigInt = createWithLength(vm, 1);
    134        
     147        JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
    135148        if (value < 0) {
    136149            bigInt->setDigit(0, static_cast<Digit>(static_cast<uint64_t>(-(value + 1)) + 1));
     
    142155    }
    143156   
    144     JSBigInt* bigInt = createWithLength(vm, 2);
    145    
     157    JSBigInt* bigInt = createWithLengthUnchecked(vm, 2);
    146158    uint64_t tempValue;
    147159    bool sign = false;
     
    167179        return createZero(vm);
    168180   
    169     JSBigInt* bigInt = createWithLength(vm, 1);
     181    JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
    170182    bigInt->setDigit(0, static_cast<Digit>(value));
    171183    return bigInt;
     
    235247{
    236248    VM& vm = exec->vm();
     249    auto scope = DECLARE_CATCH_SCOPE(vm);
    237250
    238251    if (x->isZero())
     
    242255
    243256    unsigned resultLength = x->length() + y->length();
    244     JSBigInt* result = JSBigInt::createWithLength(vm, resultLength);
     257    JSBigInt* result = JSBigInt::tryCreateWithLength(exec, resultLength);
     258    RETURN_IF_EXCEPTION(scope, nullptr);
    245259    result->initialize(InitializationType::WithZero);
    246260
     
    278292        Digit remainder;
    279293        absoluteDivWithDigitDivisor(vm, x, divisor, &quotient, remainder);
    280     } else
    281         absoluteDivWithBigIntDivisor(vm, x, y, &quotient, nullptr);
     294    } else {
     295        absoluteDivWithBigIntDivisor(exec, x, y, &quotient, nullptr);
     296        RETURN_IF_EXCEPTION(scope, nullptr);
     297    }
    282298
    283299    quotient->setSign(resultSign);
     
    289305    ASSERT(!x->isZero());
    290306
    291     JSBigInt* result = JSBigInt::createWithLength(vm, x->length());
     307    JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, x->length());
    292308    std::copy(x->dataStorage(), x->dataStorage() + x->length(), result->dataStorage());
    293309    result->setSign(x->sign());
     
    332348            return createZero(vm);
    333349
    334         remainder = createWithLength(vm, 1);
     350        remainder = createWithLengthUnchecked(vm, 1);
    335351        remainder->setDigit(0, remainderDigit);
    336     } else
    337         absoluteDivWithBigIntDivisor(vm, x, y, nullptr, &remainder);
     352    } else {
     353        absoluteDivWithBigIntDivisor(exec, x, y, nullptr, &remainder);
     354        RETURN_IF_EXCEPTION(scope, nullptr);
     355    }
    338356
    339357    remainder->setSign(x->sign());
     
    341359}
    342360
    343 JSBigInt* JSBigInt::add(VM& vm, JSBigInt* x, JSBigInt* y)
    344 {
     361JSBigInt* JSBigInt::add(ExecState* exec, JSBigInt* x, JSBigInt* y)
     362{
     363    VM& vm = exec->vm();
    345364    bool xSign = x->sign();
    346365
     
    348367    // -x + -y == -(x + y)
    349368    if (xSign == y->sign())
    350         return absoluteAdd(vm, x, y, xSign);
     369        return absoluteAdd(exec, x, y, xSign);
    351370
    352371    // x + -y == x - y == -(y - x)
     
    359378}
    360379
    361 JSBigInt* JSBigInt::sub(VM& vm, JSBigInt* x, JSBigInt* y)
    362 {
     380JSBigInt* JSBigInt::sub(ExecState* exec, JSBigInt* x, JSBigInt* y)
     381{
     382    VM& vm = exec->vm();
    363383    bool xSign = x->sign();
    364384    if (xSign != y->sign()) {
    365385        // x - (-y) == x + y
    366386        // (-x) - y == -(x + y)
    367         return absoluteAdd(vm, x, y, xSign);
     387        return absoluteAdd(exec, x, y, xSign);
    368388    }
    369389    // x - y == -(y - x)
     
    376396}
    377397
    378 JSBigInt* JSBigInt::bitwiseAnd(VM& vm, JSBigInt* x, JSBigInt* y)
    379 {
     398JSBigInt* JSBigInt::bitwiseAnd(ExecState* exec, JSBigInt* x, JSBigInt* y)
     399{
     400    VM& vm = exec->vm();
     401    auto scope = DECLARE_THROW_SCOPE(vm);
     402
    380403    if (!x->sign() && !y->sign())
    381404        return absoluteAnd(vm, x, y);
     
    385408        // (-x) & (-y) == ~(x-1) & ~(y-1) == ~((x-1) | (y-1))
    386409        // == -(((x-1) | (y-1)) + 1)
    387         JSBigInt* result = absoluteSubOne(vm, x, resultLength);
    388         JSBigInt* y1 = absoluteSubOne(vm, y, y->length());
     410        JSBigInt* result = absoluteSubOne(exec, x, resultLength);
     411        RETURN_IF_EXCEPTION(scope, nullptr);
     412
     413        JSBigInt* y1 = absoluteSubOne(exec, y, y->length());
     414        ASSERT(y1);
    389415        result = absoluteOr(vm, result, y1);
    390 
    391         return absoluteAddOne(vm, result, SignOption::Signed);
     416        scope.release();
     417        return absoluteAddOne(exec, result, SignOption::Signed);
    392418    }
    393419
     
    398424   
    399425    // x & (-y) == x & ~(y-1) == x & ~(y-1)
    400     return absoluteAndNot(vm, x, absoluteSubOne(vm, y, y->length()));
    401 }
    402 
    403 JSBigInt* JSBigInt::bitwiseOr(VM& vm, JSBigInt* x, JSBigInt* y)
    404 {
     426    JSBigInt* y1 = absoluteSubOne(exec, y, y->length());
     427    ASSERT(y1);
     428    return absoluteAndNot(vm, x, y1);
     429}
     430
     431JSBigInt* JSBigInt::bitwiseOr(ExecState* exec, JSBigInt* x, JSBigInt* y)
     432{
     433    VM& vm = exec->vm();
     434
    405435    unsigned resultLength = std::max(x->length(), y->length());
    406436
     
    411441        // (-x) | (-y) == ~(x-1) | ~(y-1) == ~((x-1) & (y-1))
    412442        // == -(((x-1) & (y-1)) + 1)
    413         JSBigInt* result = absoluteSubOne(vm, x, resultLength);
    414         JSBigInt* y1 = absoluteSubOne(vm, y, y->length());
     443        JSBigInt* result = absoluteSubOne(exec, x, resultLength);
     444        ASSERT(result);
     445        JSBigInt* y1 = absoluteSubOne(exec, y, y->length());
     446        ASSERT(y1);
    415447        result = absoluteAnd(vm, result, y1);
    416         return absoluteAddOne(vm, result, SignOption::Signed);
     448        return absoluteAddOne(exec, result, SignOption::Signed);
    417449    }
    418450   
     
    424456   
    425457    // x | (-y) == x | ~(y-1) == ~((y-1) &~ x) == -(((y-1) &~ x) + 1)
    426     JSBigInt* result = absoluteSubOne(vm, y, resultLength);
     458    JSBigInt* result = absoluteSubOne(exec, y, resultLength);
     459    ASSERT(result);
    427460    result = absoluteAndNot(vm, result, x);
    428     return absoluteAddOne(vm, result, SignOption::Signed);
    429 }
    430 
    431 JSBigInt* JSBigInt::bitwiseXor(VM& vm, JSBigInt* x, JSBigInt* y)
    432 {
     461    return absoluteAddOne(exec, result, SignOption::Signed);
     462}
     463
     464JSBigInt* JSBigInt::bitwiseXor(ExecState* exec, JSBigInt* x, JSBigInt* y)
     465{
     466    VM& vm = exec->vm();
     467    auto scope = DECLARE_THROW_SCOPE(vm);
     468
    433469    if (!x->sign() && !y->sign())
    434470        return absoluteXor(vm, x, y);
     
    438474       
    439475        // (-x) ^ (-y) == ~(x-1) ^ ~(y-1) == (x-1) ^ (y-1)
    440         JSBigInt* result = absoluteSubOne(vm, x, resultLength);
    441         JSBigInt* y1 = absoluteSubOne(vm, y, y->length());
     476        JSBigInt* result = absoluteSubOne(exec, x, resultLength);
     477        ASSERT(result);
     478        JSBigInt* y1 = absoluteSubOne(exec, y, y->length());
     479        ASSERT(y1);
    442480        return absoluteXor(vm, result, y1);
    443481    }
     
    450488   
    451489    // x ^ (-y) == x ^ ~(y-1) == ~(x ^ (y-1)) == -((x ^ (y-1)) + 1)
    452     JSBigInt* result = absoluteSubOne(vm, y, resultLength);
     490    JSBigInt* result = absoluteSubOne(exec, y, resultLength);
     491    RETURN_IF_EXCEPTION(scope, nullptr);
     492
    453493    result = absoluteXor(vm, result, x);
    454     return absoluteAddOne(vm, result, SignOption::Signed);
     494    scope.release();
     495    return absoluteAddOne(exec, result, SignOption::Signed);
    455496}
    456497
     
    752793}
    753794
    754 JSBigInt* JSBigInt::absoluteAdd(VM& vm, JSBigInt* x, JSBigInt* y, bool resultSign)
    755 {
     795JSBigInt* JSBigInt::absoluteAdd(ExecState* exec, JSBigInt* x, JSBigInt* y, bool resultSign)
     796{
     797    VM& vm = exec->vm();
     798
    756799    if (x->length() < y->length())
    757         return absoluteAdd(vm, y, x, resultSign);
     800        return absoluteAdd(exec, y, x, resultSign);
    758801
    759802    if (x->isZero()) {
     
    765808        return resultSign == x->sign() ? x : unaryMinus(vm, x);
    766809
    767     JSBigInt* result = JSBigInt::createWithLength(vm, x->length() + 1);
    768     ASSERT(result);
     810    JSBigInt* result = JSBigInt::tryCreateWithLength(exec, x->length() + 1);
     811    if (!result)
     812        return nullptr;
    769813    Digit carry = 0;
    770814    unsigned i = 0;
     
    807851        return JSBigInt::createZero(vm);
    808852
    809     JSBigInt* result = JSBigInt::createWithLength(vm, x->length());
     853    JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, x->length());
     854
    810855    Digit borrow = 0;
    811856    unsigned i = 0;
     
    852897    if (quotient != nullptr) {
    853898        if (*quotient == nullptr)
    854             *quotient = JSBigInt::createWithLength(vm, length);
     899            *quotient = JSBigInt::createWithLengthUnchecked(vm, length);
    855900
    856901        for (int i = length - 1; i >= 0; i--) {
     
    870915// interested in one of them.
    871916// See Knuth, Volume 2, section 4.3.1, Algorithm D.
    872 void JSBigInt::absoluteDivWithBigIntDivisor(VM& vm, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder)
     917void JSBigInt::absoluteDivWithBigIntDivisor(ExecState* exec, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder)
    873918{
    874919    ASSERT(divisor->length() >= 2);
    875920    ASSERT(dividend->length() >= divisor->length());
     921    VM& vm = exec->vm();
     922    auto scope = DECLARE_CATCH_SCOPE(vm);
    876923
    877924    // The unusual variable names inside this function are consistent with
     
    885932    JSBigInt* q = nullptr;
    886933    if (quotient != nullptr)
    887         q = createWithLength(vm, m + 1);
     934        q = createWithLengthUnchecked(exec->vm(), m + 1);
    888935   
    889936    // In each iteration, {qhatv} holds {divisor} * {current quotient digit}.
    890937    // "v" is the book's name for {divisor}, "qhat" the current quotient digit.
    891     JSBigInt* qhatv = createWithLength(vm, n + 1);
     938    JSBigInt* qhatv = tryCreateWithLength(exec, n + 1);
     939    RETURN_IF_EXCEPTION(scope, void());
    892940   
    893941    // D1.
     
    899947    unsigned shift = sizeof(lastDigit) == 8 ? clz64(lastDigit) : clz32(lastDigit);
    900948
    901     if (shift > 0)
    902         divisor = absoluteLeftShiftAlwaysCopy(vm, divisor, shift, LeftShiftMode::SameSizeResult);
     949    if (shift > 0) {
     950        divisor = absoluteLeftShiftAlwaysCopy(exec, divisor, shift, LeftShiftMode::SameSizeResult);
     951        RETURN_IF_EXCEPTION(scope, void());
     952    }
    903953
    904954    // Holds the (continuously updated) remaining part of the dividend, which
    905955    // eventually becomes the remainder.
    906     JSBigInt* u = absoluteLeftShiftAlwaysCopy(vm, dividend, shift, LeftShiftMode::AlwaysAddOneDigit);
     956    JSBigInt* u = absoluteLeftShiftAlwaysCopy(exec, dividend, shift, LeftShiftMode::AlwaysAddOneDigit);
     957    RETURN_IF_EXCEPTION(scope, void());
    907958
    908959    // D2.
     
    10321083
    10331084// Always copies the input, even when {shift} == 0.
    1034 JSBigInt* JSBigInt::absoluteLeftShiftAlwaysCopy(VM& vm, JSBigInt* x, unsigned shift, LeftShiftMode mode)
     1085JSBigInt* JSBigInt::absoluteLeftShiftAlwaysCopy(ExecState* exec, JSBigInt* x, unsigned shift, LeftShiftMode mode)
    10351086{
    10361087    ASSERT(shift < digitBits);
     
    10391090    unsigned n = x->length();
    10401091    unsigned resultLength = mode == LeftShiftMode::AlwaysAddOneDigit ? n + 1 : n;
    1041     JSBigInt* result = createWithLength(vm, resultLength);
     1092    JSBigInt* result = tryCreateWithLength(exec, resultLength);
     1093    if (!result)
     1094        return nullptr;
    10421095
    10431096    if (!shift) {
     
    10961149    ASSERT(numPairs == std::min(xLength, yLength));
    10971150    unsigned resultLength = extraDigits == ExtraDigitsHandling::Copy ? xLength : numPairs;
    1098     JSBigInt* result = createWithLength(vm, resultLength);
    1099 
     1151    JSBigInt* result = createWithLengthUnchecked(vm, resultLength);
    11001152    unsigned i = 0;
    11011153    for (; i < numPairs; i++)
     
    11451197}
    11461198   
    1147 JSBigInt* JSBigInt::absoluteAddOne(VM& vm, JSBigInt* x, SignOption signOption)
     1199JSBigInt* JSBigInt::absoluteAddOne(ExecState* exec, JSBigInt* x, SignOption signOption)
    11481200{
    11491201    unsigned inputLength = x->length();
     
    11591211
    11601212    unsigned resultLength = inputLength + willOverflow;
    1161     JSBigInt* result = createWithLength(vm, resultLength);
     1213    JSBigInt* result = tryCreateWithLength(exec, resultLength);
     1214    if (!result)
     1215        return nullptr;
    11621216
    11631217    Digit carry = 1;
     
    11731227
    11741228    result->setSign(signOption == SignOption::Signed);
    1175     return result->rightTrim(vm);
    1176 }
    1177 
    1178 // Like the above, but you can specify that the allocated result should have
    1179 // length {resultLength}, which must be at least as large as {x->length()}.
    1180 JSBigInt* JSBigInt::absoluteSubOne(VM& vm, JSBigInt* x, unsigned resultLength)
     1229    return result->rightTrim(exec->vm());
     1230}
     1231
     1232JSBigInt* JSBigInt::absoluteSubOne(ExecState* exec, JSBigInt* x, unsigned resultLength)
    11811233{
    11821234    ASSERT(!x->isZero());
    11831235    ASSERT(resultLength >= x->length());
    1184     JSBigInt* result = createWithLength(vm, resultLength);
     1236    VM& vm = exec->vm();
     1237    auto scope = DECLARE_CATCH_SCOPE(vm);
     1238
     1239    JSBigInt* result = tryCreateWithLength(exec, resultLength);
     1240    RETURN_IF_EXCEPTION(scope, nullptr);
    11851241
    11861242    unsigned length = x->length();
     
    13551411            Digit chunk;
    13561412            absoluteDivWithDigitDivisor(vm, *dividend, chunkDivisor, &rest, chunk);
    1357             ASSERT(rest);
    1358 
    13591413            dividend = &rest;
    13601414            for (unsigned i = 0; i < chunkChars; i++) {
     
    14151469
    14161470    unsigned newLength = nonZeroIndex + 1;
    1417     JSBigInt* trimmedBigInt = createWithLength(vm, newLength);
    1418     RELEASE_ASSERT(trimmedBigInt);
     1471    JSBigInt* trimmedBigInt = createWithLengthUnchecked(vm, newLength);
    14191472    std::copy(dataStorage(), dataStorage() + newLength, trimmedBigInt->dataStorage());
    14201473
     
    14401493            unsigned length = (bitsMin + digitBits - 1) / digitBits;
    14411494            if (length <= maxLength) {
    1442                 JSBigInt* result = JSBigInt::createWithLength(vm, length);
     1495                JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, length);
    14431496                return result;
    14441497            }
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.h

    r237296 r238132  
    5252    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
    5353    static JSBigInt* createZero(VM&);
    54     static JSBigInt* createWithLength(VM&, unsigned length);
     54    static JSBigInt* tryCreateWithLength(ExecState*, unsigned length);
     55    static JSBigInt* createWithLengthUnchecked(VM&, unsigned length);
    5556
    5657    static JSBigInt* createFrom(VM&, int32_t value);
     
    109110    ComparisonResult static compareToDouble(JSBigInt* x, double y);
    110111
    111     static JSBigInt* add(VM&, JSBigInt* x, JSBigInt* y);
    112     static JSBigInt* sub(VM&, JSBigInt* x, JSBigInt* y);
     112    static JSBigInt* add(ExecState*, JSBigInt* x, JSBigInt* y);
     113    static JSBigInt* sub(ExecState*, JSBigInt* x, JSBigInt* y);
    113114    static JSBigInt* divide(ExecState*, JSBigInt* x, JSBigInt* y);
    114115    static JSBigInt* remainder(ExecState*, JSBigInt* x, JSBigInt* y);
    115116    static JSBigInt* unaryMinus(VM&, JSBigInt* x);
    116117
    117     static JSBigInt* bitwiseAnd(VM&, JSBigInt* x, JSBigInt* y);
    118     static JSBigInt* bitwiseOr(VM&, JSBigInt* x, JSBigInt* y);
    119     static JSBigInt* bitwiseXor(VM&, JSBigInt* x, JSBigInt* y);
     118    static JSBigInt* bitwiseAnd(ExecState*, JSBigInt* x, JSBigInt* y);
     119    static JSBigInt* bitwiseOr(ExecState*, JSBigInt* x, JSBigInt* y);
     120    static JSBigInt* bitwiseXor(ExecState*, JSBigInt* x, JSBigInt* y);
    120121
    121122private:
     
    140141    static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned, JSBigInt* result);
    141142    static void multiplyAccumulate(JSBigInt* multiplicand, Digit multiplier, JSBigInt* accumulator, unsigned accumulatorIndex);
    142     static void absoluteDivWithBigIntDivisor(VM&, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder);
     143    static void absoluteDivWithBigIntDivisor(ExecState*, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder);
    143144   
    144145    enum class LeftShiftMode {
     
    147148    };
    148149   
    149     static JSBigInt* absoluteLeftShiftAlwaysCopy(VM&, JSBigInt* x, unsigned shift, LeftShiftMode);
     150    static JSBigInt* absoluteLeftShiftAlwaysCopy(ExecState*, JSBigInt* x, unsigned shift, LeftShiftMode);
    150151    static bool productGreaterThan(Digit factor1, Digit factor2, Digit high, Digit low);
    151152
     
    177178    };
    178179
    179     static JSBigInt* absoluteAddOne(VM&, JSBigInt* x, SignOption);
    180     static JSBigInt* absoluteSubOne(VM&, JSBigInt* x, unsigned resultLength);
     180    static JSBigInt* absoluteAddOne(ExecState*, JSBigInt* x, SignOption);
     181    static JSBigInt* absoluteSubOne(ExecState*, JSBigInt* x, unsigned resultLength);
    181182
    182183    // Digit arithmetic helpers.
     
    204205
    205206    void inplaceMultiplyAdd(Digit multiplier, Digit part);
    206     static JSBigInt* absoluteAdd(VM&, JSBigInt* x, JSBigInt* y, bool resultSign);
     207    static JSBigInt* absoluteAdd(ExecState*, JSBigInt* x, JSBigInt* y, bool resultSign);
    207208    static JSBigInt* absoluteSub(VM&, JSBigInt* x, JSBigInt* y, bool resultSign);
    208209   
  • trunk/Source/JavaScriptCore/runtime/Operations.cpp

    r236697 r238132  
    7070
    7171    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    72         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric))
    73             return JSBigInt::add(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     72        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
     73            scope.release();
     74            return JSBigInt::add(callFrame, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     75        }
    7476
    7577        return throwTypeError(callFrame, scope, "Invalid mix of BigInt and other type in addition."_s);
  • trunk/Source/JavaScriptCore/runtime/Operations.h

    r236804 r238132  
    349349
    350350    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    351         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric))
    352             return JSBigInt::sub(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     351        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
     352            scope.release();
     353            return JSBigInt::sub(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     354        }
    353355
    354356        return throwTypeError(exec, scope, "Invalid mix of BigInt and other type in subtraction."_s);
     
    369371
    370372    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
    371         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric))
     373        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
     374            scope.release();
    372375            return JSBigInt::multiply(state, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
     376        }
    373377
    374378        throwTypeError(state, scope, "Invalid mix of BigInt and other type in multiplication."_s);
Note: See TracChangeset for help on using the changeset viewer.