Changeset 238425 in webkit


Ignore:
Timestamp:
Nov 21, 2018 10:38:11 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 and Yusuke Suzuki.

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::tryCreateWithLength is not greater than JSBigInt::maxLength.
When the length is greater than JSBigInt::maxLength, we then throw OOM
exception.
This required us to 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

    r238421 r238425  
     12018-11-21  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 and Yusuke Suzuki.
     7
     8        * stress/big-int-out-of-memory-tests.js: Added.
     9
    1102018-11-20  Mark Lam  <mark.lam@apple.com>
    211
  • trunk/Source/JavaScriptCore/ChangeLog

    r238421 r238425  
     12018-11-21  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 and Yusuke Suzuki.
     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::tryCreateWithLength` is not greater than JSBigInt::maxLength.
     12        When the length is greater than JSBigInt::maxLength, we then throw OOM
     13        exception.
     14        This required us to 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-20  Mark Lam  <mark.lam@apple.com>
    260
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r238162 r238425  
    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

    r238162 r238425  
    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

    r238162 r238425  
    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

    r238156 r238425  
    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)
    95 {
     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)
     110{
     111    ASSERT(length <= maxLength);
    96112    JSBigInt* bigInt = new (NotNull, allocateCell<JSBigInt>(vm.heap, allocationSize(length))) JSBigInt(vm, vm.bigIntStructure.get(), length);
    97113    bigInt->finishCreation(vm);
     
    104120        return createZero(vm);
    105121   
    106     JSBigInt* bigInt = createWithLength(vm, 1);
    107    
     122    JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
    108123    if (value < 0) {
    109124        bigInt->setDigit(0, static_cast<Digit>(-1 * static_cast<int64_t>(value)));
     
    120135        return createZero(vm);
    121136   
    122     JSBigInt* bigInt = createWithLength(vm, 1);
     137    JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
    123138    bigInt->setDigit(0, static_cast<Digit>(value));
    124139    return bigInt;
     
    131146   
    132147    if (sizeof(Digit) == 8) {
    133         JSBigInt* bigInt = createWithLength(vm, 1);
    134        
     148        JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
    135149        if (value < 0) {
    136150            bigInt->setDigit(0, static_cast<Digit>(static_cast<uint64_t>(-(value + 1)) + 1));
     
    142156    }
    143157   
    144     JSBigInt* bigInt = createWithLength(vm, 2);
    145    
     158    JSBigInt* bigInt = createWithLengthUnchecked(vm, 2);
    146159    uint64_t tempValue;
    147160    bool sign = false;
     
    167180        return createZero(vm);
    168181   
    169     JSBigInt* bigInt = createWithLength(vm, 1);
     182    JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
    170183    bigInt->setDigit(0, static_cast<Digit>(value));
    171184    return bigInt;
     
    235248{
    236249    VM& vm = exec->vm();
     250    auto scope = DECLARE_THROW_SCOPE(vm);
    237251
    238252    if (x->isZero())
     
    242256
    243257    unsigned resultLength = x->length() + y->length();
    244     JSBigInt* result = JSBigInt::createWithLength(vm, resultLength);
     258    JSBigInt* result = JSBigInt::tryCreateWithLength(exec, resultLength);
     259    RETURN_IF_EXCEPTION(scope, nullptr);
    245260    result->initialize(InitializationType::WithZero);
    246261
     
    278293        Digit remainder;
    279294        absoluteDivWithDigitDivisor(vm, x, divisor, &quotient, remainder);
    280     } else
    281         absoluteDivWithBigIntDivisor(vm, x, y, &quotient, nullptr);
     295    } else {
     296        absoluteDivWithBigIntDivisor(exec, x, y, &quotient, nullptr);
     297        RETURN_IF_EXCEPTION(scope, nullptr);
     298    }
    282299
    283300    quotient->setSign(resultSign);
     
    289306    ASSERT(!x->isZero());
    290307
    291     JSBigInt* result = JSBigInt::createWithLength(vm, x->length());
     308    JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, x->length());
    292309    std::copy(x->dataStorage(), x->dataStorage() + x->length(), result->dataStorage());
    293310    result->setSign(x->sign());
     
    332349            return createZero(vm);
    333350
    334         remainder = createWithLength(vm, 1);
     351        remainder = createWithLengthUnchecked(vm, 1);
    335352        remainder->setDigit(0, remainderDigit);
    336     } else
    337         absoluteDivWithBigIntDivisor(vm, x, y, nullptr, &remainder);
     353    } else {
     354        absoluteDivWithBigIntDivisor(exec, x, y, nullptr, &remainder);
     355        RETURN_IF_EXCEPTION(scope, nullptr);
     356    }
    338357
    339358    remainder->setSign(x->sign());
     
    341360}
    342361
    343 JSBigInt* JSBigInt::add(VM& vm, JSBigInt* x, JSBigInt* y)
    344 {
     362JSBigInt* JSBigInt::add(ExecState* exec, JSBigInt* x, JSBigInt* y)
     363{
     364    VM& vm = exec->vm();
    345365    bool xSign = x->sign();
    346366
     
    348368    // -x + -y == -(x + y)
    349369    if (xSign == y->sign())
    350         return absoluteAdd(vm, x, y, xSign);
     370        return absoluteAdd(exec, x, y, xSign);
    351371
    352372    // x + -y == x - y == -(y - x)
     
    359379}
    360380
    361 JSBigInt* JSBigInt::sub(VM& vm, JSBigInt* x, JSBigInt* y)
    362 {
     381JSBigInt* JSBigInt::sub(ExecState* exec, JSBigInt* x, JSBigInt* y)
     382{
     383    VM& vm = exec->vm();
    363384    bool xSign = x->sign();
    364385    if (xSign != y->sign()) {
    365386        // x - (-y) == x + y
    366387        // (-x) - y == -(x + y)
    367         return absoluteAdd(vm, x, y, xSign);
     388        return absoluteAdd(exec, x, y, xSign);
    368389    }
    369390    // x - y == -(y - x)
     
    376397}
    377398
    378 JSBigInt* JSBigInt::bitwiseAnd(VM& vm, JSBigInt* x, JSBigInt* y)
    379 {
    380     if (!x->sign() && !y->sign())
     399JSBigInt* JSBigInt::bitwiseAnd(ExecState* exec, JSBigInt* x, JSBigInt* y)
     400{
     401    VM& vm = exec->vm();
     402    auto scope = DECLARE_THROW_SCOPE(vm);
     403
     404    if (!x->sign() && !y->sign()) {
     405        scope.release();
    381406        return absoluteAnd(vm, x, y);
     407    }
    382408   
    383409    if (x->sign() && y->sign()) {
     
    385411        // (-x) & (-y) == ~(x-1) & ~(y-1) == ~((x-1) | (y-1))
    386412        // == -(((x-1) | (y-1)) + 1)
    387         JSBigInt* result = absoluteSubOne(vm, x, resultLength);
    388         JSBigInt* y1 = absoluteSubOne(vm, y, y->length());
     413        JSBigInt* result = absoluteSubOne(exec, x, resultLength);
     414        RETURN_IF_EXCEPTION(scope, nullptr);
     415
     416        JSBigInt* y1 = absoluteSubOne(exec, y, y->length());
     417        RETURN_IF_EXCEPTION(scope, nullptr);
    389418        result = absoluteOr(vm, result, y1);
    390 
    391         return absoluteAddOne(vm, result, SignOption::Signed);
     419        scope.release();
     420        return absoluteAddOne(exec, result, SignOption::Signed);
    392421    }
    393422
     
    398427   
    399428    // 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 {
     429    JSBigInt* y1 = absoluteSubOne(exec, y, y->length());
     430    RETURN_IF_EXCEPTION(scope, nullptr);
     431    return absoluteAndNot(vm, x, y1);
     432}
     433
     434JSBigInt* JSBigInt::bitwiseOr(ExecState* exec, JSBigInt* x, JSBigInt* y)
     435{
     436    VM& vm = exec->vm();
     437    auto scope = DECLARE_THROW_SCOPE(vm);
     438
    405439    unsigned resultLength = std::max(x->length(), y->length());
    406440
    407     if (!x->sign() && !y->sign())
     441    if (!x->sign() && !y->sign()) {
     442        scope.release();
    408443        return absoluteOr(vm, x, y);
     444    }
    409445   
    410446    if (x->sign() && y->sign()) {
    411447        // (-x) | (-y) == ~(x-1) | ~(y-1) == ~((x-1) & (y-1))
    412448        // == -(((x-1) & (y-1)) + 1)
    413         JSBigInt* result = absoluteSubOne(vm, x, resultLength);
    414         JSBigInt* y1 = absoluteSubOne(vm, y, y->length());
     449        JSBigInt* result = absoluteSubOne(exec, x, resultLength);
     450        RETURN_IF_EXCEPTION(scope, nullptr);
     451        JSBigInt* y1 = absoluteSubOne(exec, y, y->length());
     452        RETURN_IF_EXCEPTION(scope, nullptr);
    415453        result = absoluteAnd(vm, result, y1);
    416         return absoluteAddOne(vm, result, SignOption::Signed);
     454        RETURN_IF_EXCEPTION(scope, nullptr);
     455
     456        scope.release();
     457        return absoluteAddOne(exec, result, SignOption::Signed);
    417458    }
    418459   
     
    424465   
    425466    // x | (-y) == x | ~(y-1) == ~((y-1) &~ x) == -(((y-1) &~ x) + 1)
    426     JSBigInt* result = absoluteSubOne(vm, y, resultLength);
     467    JSBigInt* result = absoluteSubOne(exec, y, resultLength);
     468    RETURN_IF_EXCEPTION(scope, nullptr);
    427469    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 {
    433     if (!x->sign() && !y->sign())
     470
     471    scope.release();
     472    return absoluteAddOne(exec, result, SignOption::Signed);
     473}
     474
     475JSBigInt* JSBigInt::bitwiseXor(ExecState* exec, JSBigInt* x, JSBigInt* y)
     476{
     477    VM& vm = exec->vm();
     478    auto scope = DECLARE_THROW_SCOPE(vm);
     479
     480    if (!x->sign() && !y->sign()) {
     481        scope.release();
    434482        return absoluteXor(vm, x, y);
     483    }
    435484   
    436485    if (x->sign() && y->sign()) {
     
    438487       
    439488        // (-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());
     489        JSBigInt* result = absoluteSubOne(exec, x, resultLength);
     490        RETURN_IF_EXCEPTION(scope, nullptr);
     491        JSBigInt* y1 = absoluteSubOne(exec, y, y->length());
     492        RETURN_IF_EXCEPTION(scope, nullptr);
     493
     494        scope.release();
    442495        return absoluteXor(vm, result, y1);
    443496    }
     
    450503   
    451504    // x ^ (-y) == x ^ ~(y-1) == ~(x ^ (y-1)) == -((x ^ (y-1)) + 1)
    452     JSBigInt* result = absoluteSubOne(vm, y, resultLength);
     505    JSBigInt* result = absoluteSubOne(exec, y, resultLength);
     506    RETURN_IF_EXCEPTION(scope, nullptr);
     507
    453508    result = absoluteXor(vm, result, x);
    454     return absoluteAddOne(vm, result, SignOption::Signed);
     509    scope.release();
     510    return absoluteAddOne(exec, result, SignOption::Signed);
    455511}
    456512
     
    752808}
    753809
    754 JSBigInt* JSBigInt::absoluteAdd(VM& vm, JSBigInt* x, JSBigInt* y, bool resultSign)
    755 {
     810JSBigInt* JSBigInt::absoluteAdd(ExecState* exec, JSBigInt* x, JSBigInt* y, bool resultSign)
     811{
     812    VM& vm = exec->vm();
     813
    756814    if (x->length() < y->length())
    757         return absoluteAdd(vm, y, x, resultSign);
     815        return absoluteAdd(exec, y, x, resultSign);
    758816
    759817    if (x->isZero()) {
     
    765823        return resultSign == x->sign() ? x : unaryMinus(vm, x);
    766824
    767     JSBigInt* result = JSBigInt::createWithLength(vm, x->length() + 1);
    768     ASSERT(result);
     825    JSBigInt* result = JSBigInt::tryCreateWithLength(exec, x->length() + 1);
     826    if (!result)
     827        return nullptr;
    769828    Digit carry = 0;
    770829    unsigned i = 0;
     
    807866        return JSBigInt::createZero(vm);
    808867
    809     JSBigInt* result = JSBigInt::createWithLength(vm, x->length());
     868    JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, x->length());
     869
    810870    Digit borrow = 0;
    811871    unsigned i = 0;
     
    852912    if (quotient != nullptr) {
    853913        if (*quotient == nullptr)
    854             *quotient = JSBigInt::createWithLength(vm, length);
     914            *quotient = JSBigInt::createWithLengthUnchecked(vm, length);
    855915
    856916        for (int i = length - 1; i >= 0; i--) {
     
    870930// interested in one of them.
    871931// See Knuth, Volume 2, section 4.3.1, Algorithm D.
    872 void JSBigInt::absoluteDivWithBigIntDivisor(VM& vm, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder)
     932void JSBigInt::absoluteDivWithBigIntDivisor(ExecState* exec, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder)
    873933{
    874934    ASSERT(divisor->length() >= 2);
    875935    ASSERT(dividend->length() >= divisor->length());
     936    VM& vm = exec->vm();
     937    auto scope = DECLARE_THROW_SCOPE(vm);
    876938
    877939    // The unusual variable names inside this function are consistent with
     
    885947    JSBigInt* q = nullptr;
    886948    if (quotient != nullptr)
    887         q = createWithLength(vm, m + 1);
     949        q = createWithLengthUnchecked(exec->vm(), m + 1);
    888950   
    889951    // In each iteration, {qhatv} holds {divisor} * {current quotient digit}.
    890952    // "v" is the book's name for {divisor}, "qhat" the current quotient digit.
    891     JSBigInt* qhatv = createWithLength(vm, n + 1);
     953    JSBigInt* qhatv = tryCreateWithLength(exec, n + 1);
     954    RETURN_IF_EXCEPTION(scope, void());
    892955   
    893956    // D1.
     
    899962    unsigned shift = sizeof(lastDigit) == 8 ? clz64(lastDigit) : clz32(lastDigit);
    900963
    901     if (shift > 0)
    902         divisor = absoluteLeftShiftAlwaysCopy(vm, divisor, shift, LeftShiftMode::SameSizeResult);
     964    if (shift > 0) {
     965        divisor = absoluteLeftShiftAlwaysCopy(exec, divisor, shift, LeftShiftMode::SameSizeResult);
     966        RETURN_IF_EXCEPTION(scope, void());
     967    }
    903968
    904969    // Holds the (continuously updated) remaining part of the dividend, which
    905970    // eventually becomes the remainder.
    906     JSBigInt* u = absoluteLeftShiftAlwaysCopy(vm, dividend, shift, LeftShiftMode::AlwaysAddOneDigit);
     971    JSBigInt* u = absoluteLeftShiftAlwaysCopy(exec, dividend, shift, LeftShiftMode::AlwaysAddOneDigit);
     972    RETURN_IF_EXCEPTION(scope, void());
    907973
    908974    // D2.
     
    10321098
    10331099// Always copies the input, even when {shift} == 0.
    1034 JSBigInt* JSBigInt::absoluteLeftShiftAlwaysCopy(VM& vm, JSBigInt* x, unsigned shift, LeftShiftMode mode)
     1100JSBigInt* JSBigInt::absoluteLeftShiftAlwaysCopy(ExecState* exec, JSBigInt* x, unsigned shift, LeftShiftMode mode)
    10351101{
    10361102    ASSERT(shift < digitBits);
     
    10391105    unsigned n = x->length();
    10401106    unsigned resultLength = mode == LeftShiftMode::AlwaysAddOneDigit ? n + 1 : n;
    1041     JSBigInt* result = createWithLength(vm, resultLength);
     1107    JSBigInt* result = tryCreateWithLength(exec, resultLength);
     1108    if (!result)
     1109        return nullptr;
    10421110
    10431111    if (!shift) {
     
    10961164    ASSERT(numPairs == std::min(xLength, yLength));
    10971165    unsigned resultLength = extraDigits == ExtraDigitsHandling::Copy ? xLength : numPairs;
    1098     JSBigInt* result = createWithLength(vm, resultLength);
    1099 
     1166    JSBigInt* result = createWithLengthUnchecked(vm, resultLength);
    11001167    unsigned i = 0;
    11011168    for (; i < numPairs; i++)
     
    11451212}
    11461213   
    1147 JSBigInt* JSBigInt::absoluteAddOne(VM& vm, JSBigInt* x, SignOption signOption)
     1214JSBigInt* JSBigInt::absoluteAddOne(ExecState* exec, JSBigInt* x, SignOption signOption)
    11481215{
    11491216    unsigned inputLength = x->length();
     
    11591226
    11601227    unsigned resultLength = inputLength + willOverflow;
    1161     JSBigInt* result = createWithLength(vm, resultLength);
     1228    JSBigInt* result = tryCreateWithLength(exec, resultLength);
     1229    if (!result)
     1230        return nullptr;
    11621231
    11631232    Digit carry = 1;
     
    11731242
    11741243    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)
     1244    return result->rightTrim(exec->vm());
     1245}
     1246
     1247JSBigInt* JSBigInt::absoluteSubOne(ExecState* exec, JSBigInt* x, unsigned resultLength)
    11811248{
    11821249    ASSERT(!x->isZero());
    11831250    ASSERT(resultLength >= x->length());
    1184     JSBigInt* result = createWithLength(vm, resultLength);
     1251    VM& vm = exec->vm();
     1252    auto scope = DECLARE_THROW_SCOPE(vm);
     1253
     1254    JSBigInt* result = tryCreateWithLength(exec, resultLength);
     1255    RETURN_IF_EXCEPTION(scope, nullptr);
    11851256
    11861257    unsigned length = x->length();
     
    13551426            Digit chunk;
    13561427            absoluteDivWithDigitDivisor(vm, *dividend, chunkDivisor, &rest, chunk);
    1357             ASSERT(rest);
    1358 
    13591428            dividend = &rest;
    13601429            for (unsigned i = 0; i < chunkChars; i++) {
     
    14151484
    14161485    unsigned newLength = nonZeroIndex + 1;
    1417     JSBigInt* trimmedBigInt = createWithLength(vm, newLength);
    1418     RELEASE_ASSERT(trimmedBigInt);
     1486    JSBigInt* trimmedBigInt = createWithLengthUnchecked(vm, newLength);
    14191487    std::copy(dataStorage(), dataStorage() + newLength, trimmedBigInt->dataStorage());
    14201488
     
    14401508            unsigned length = (bitsMin + digitBits - 1) / digitBits;
    14411509            if (length <= maxLength) {
    1442                 JSBigInt* result = JSBigInt::createWithLength(vm, length);
     1510                JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, length);
    14431511                return result;
    14441512            }
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.h

    r238156 r238425  
    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

    r238156 r238425  
    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

    r238156 r238425  
    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.