Changeset 238425 in webkit
- Timestamp:
- Nov 21, 2018 10:38:11 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r238421 r238425 1 2018-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 1 10 2018-11-20 Mark Lam <mark.lam@apple.com> 2 11 -
trunk/Source/JavaScriptCore/ChangeLog
r238421 r238425 1 2018-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 1 59 2018-11-20 Mark Lam <mark.lam@apple.com> 2 60 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r238162 r238425 350 350 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 351 351 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)); 353 353 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 354 354 return JSValue::encode(result); … … 377 377 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 378 378 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)); 380 380 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 381 381 return JSValue::encode(result); … … 1295 1295 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2); 1296 1296 1297 return JSBigInt::sub( *vm, leftOperand, rightOperand);1297 return JSBigInt::sub(exec, leftOperand, rightOperand); 1298 1298 } 1299 1299 … … 1306 1306 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2); 1307 1307 1308 return JSBigInt::bitwiseAnd( *vm, leftOperand, rightOperand);1308 return JSBigInt::bitwiseAnd(exec, leftOperand, rightOperand); 1309 1309 } 1310 1310 … … 1317 1317 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2); 1318 1318 1319 return JSBigInt::add( *vm, leftOperand, rightOperand);1319 return JSBigInt::add(exec, leftOperand, rightOperand); 1320 1320 } 1321 1321 … … 1328 1328 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2); 1329 1329 1330 return JSBigInt::bitwiseOr( *vm, leftOperand, rightOperand);1330 return JSBigInt::bitwiseOr(exec, leftOperand, rightOperand); 1331 1331 } 1332 1332 -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r238162 r238425 2767 2767 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 2768 2768 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))); 2773 2771 2774 2772 double number = primValue.toNumber(exec); -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r238162 r238425 564 564 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 565 565 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(); 567 568 RETURN_WITH_PROFILING(result, { 568 569 updateArithProfileForBinaryArithOp(exec, pc, result, left, right); … … 700 701 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 701 702 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)); 703 704 CHECK_EXCEPTION(); 704 705 RETURN_PROFILED(result); … … 721 722 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 722 723 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)); 724 725 CHECK_EXCEPTION(); 725 726 RETURN_PROFILED(result); … … 742 743 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 743 744 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)); 745 746 CHECK_EXCEPTION(); 746 747 RETURN(result); -
trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp
r238156 r238425 82 82 JSBigInt* JSBigInt::createZero(VM& vm) 83 83 { 84 JSBigInt* zeroBigInt = createWithLength (vm, 0);84 JSBigInt* zeroBigInt = createWithLengthUnchecked(vm, 0); 85 85 return zeroBigInt; 86 86 } … … 92 92 } 93 93 94 JSBigInt* JSBigInt::createWithLength(VM& vm, unsigned length) 95 { 94 JSBigInt* 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 109 JSBigInt* JSBigInt::createWithLengthUnchecked(VM& vm, unsigned length) 110 { 111 ASSERT(length <= maxLength); 96 112 JSBigInt* bigInt = new (NotNull, allocateCell<JSBigInt>(vm.heap, allocationSize(length))) JSBigInt(vm, vm.bigIntStructure.get(), length); 97 113 bigInt->finishCreation(vm); … … 104 120 return createZero(vm); 105 121 106 JSBigInt* bigInt = createWithLength(vm, 1); 107 122 JSBigInt* bigInt = createWithLengthUnchecked(vm, 1); 108 123 if (value < 0) { 109 124 bigInt->setDigit(0, static_cast<Digit>(-1 * static_cast<int64_t>(value))); … … 120 135 return createZero(vm); 121 136 122 JSBigInt* bigInt = createWithLength (vm, 1);137 JSBigInt* bigInt = createWithLengthUnchecked(vm, 1); 123 138 bigInt->setDigit(0, static_cast<Digit>(value)); 124 139 return bigInt; … … 131 146 132 147 if (sizeof(Digit) == 8) { 133 JSBigInt* bigInt = createWithLength(vm, 1); 134 148 JSBigInt* bigInt = createWithLengthUnchecked(vm, 1); 135 149 if (value < 0) { 136 150 bigInt->setDigit(0, static_cast<Digit>(static_cast<uint64_t>(-(value + 1)) + 1)); … … 142 156 } 143 157 144 JSBigInt* bigInt = createWithLength(vm, 2); 145 158 JSBigInt* bigInt = createWithLengthUnchecked(vm, 2); 146 159 uint64_t tempValue; 147 160 bool sign = false; … … 167 180 return createZero(vm); 168 181 169 JSBigInt* bigInt = createWithLength (vm, 1);182 JSBigInt* bigInt = createWithLengthUnchecked(vm, 1); 170 183 bigInt->setDigit(0, static_cast<Digit>(value)); 171 184 return bigInt; … … 235 248 { 236 249 VM& vm = exec->vm(); 250 auto scope = DECLARE_THROW_SCOPE(vm); 237 251 238 252 if (x->isZero()) … … 242 256 243 257 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); 245 260 result->initialize(InitializationType::WithZero); 246 261 … … 278 293 Digit remainder; 279 294 absoluteDivWithDigitDivisor(vm, x, divisor, "ient, remainder); 280 } else 281 absoluteDivWithBigIntDivisor(vm, x, y, "ient, nullptr); 295 } else { 296 absoluteDivWithBigIntDivisor(exec, x, y, "ient, nullptr); 297 RETURN_IF_EXCEPTION(scope, nullptr); 298 } 282 299 283 300 quotient->setSign(resultSign); … … 289 306 ASSERT(!x->isZero()); 290 307 291 JSBigInt* result = JSBigInt::createWithLength (vm, x->length());308 JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, x->length()); 292 309 std::copy(x->dataStorage(), x->dataStorage() + x->length(), result->dataStorage()); 293 310 result->setSign(x->sign()); … … 332 349 return createZero(vm); 333 350 334 remainder = createWithLength (vm, 1);351 remainder = createWithLengthUnchecked(vm, 1); 335 352 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 } 338 357 339 358 remainder->setSign(x->sign()); … … 341 360 } 342 361 343 JSBigInt* JSBigInt::add(VM& vm, JSBigInt* x, JSBigInt* y) 344 { 362 JSBigInt* JSBigInt::add(ExecState* exec, JSBigInt* x, JSBigInt* y) 363 { 364 VM& vm = exec->vm(); 345 365 bool xSign = x->sign(); 346 366 … … 348 368 // -x + -y == -(x + y) 349 369 if (xSign == y->sign()) 350 return absoluteAdd( vm, x, y, xSign);370 return absoluteAdd(exec, x, y, xSign); 351 371 352 372 // x + -y == x - y == -(y - x) … … 359 379 } 360 380 361 JSBigInt* JSBigInt::sub(VM& vm, JSBigInt* x, JSBigInt* y) 362 { 381 JSBigInt* JSBigInt::sub(ExecState* exec, JSBigInt* x, JSBigInt* y) 382 { 383 VM& vm = exec->vm(); 363 384 bool xSign = x->sign(); 364 385 if (xSign != y->sign()) { 365 386 // x - (-y) == x + y 366 387 // (-x) - y == -(x + y) 367 return absoluteAdd( vm, x, y, xSign);388 return absoluteAdd(exec, x, y, xSign); 368 389 } 369 390 // x - y == -(y - x) … … 376 397 } 377 398 378 JSBigInt* JSBigInt::bitwiseAnd(VM& vm, JSBigInt* x, JSBigInt* y) 379 { 380 if (!x->sign() && !y->sign()) 399 JSBigInt* 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(); 381 406 return absoluteAnd(vm, x, y); 407 } 382 408 383 409 if (x->sign() && y->sign()) { … … 385 411 // (-x) & (-y) == ~(x-1) & ~(y-1) == ~((x-1) | (y-1)) 386 412 // == -(((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); 389 418 result = absoluteOr(vm, result, y1); 390 391 return absoluteAddOne( vm, result, SignOption::Signed);419 scope.release(); 420 return absoluteAddOne(exec, result, SignOption::Signed); 392 421 } 393 422 … … 398 427 399 428 // 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 434 JSBigInt* JSBigInt::bitwiseOr(ExecState* exec, JSBigInt* x, JSBigInt* y) 435 { 436 VM& vm = exec->vm(); 437 auto scope = DECLARE_THROW_SCOPE(vm); 438 405 439 unsigned resultLength = std::max(x->length(), y->length()); 406 440 407 if (!x->sign() && !y->sign()) 441 if (!x->sign() && !y->sign()) { 442 scope.release(); 408 443 return absoluteOr(vm, x, y); 444 } 409 445 410 446 if (x->sign() && y->sign()) { 411 447 // (-x) | (-y) == ~(x-1) | ~(y-1) == ~((x-1) & (y-1)) 412 448 // == -(((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); 415 453 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); 417 458 } 418 459 … … 424 465 425 466 // 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); 427 469 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 475 JSBigInt* 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(); 434 482 return absoluteXor(vm, x, y); 483 } 435 484 436 485 if (x->sign() && y->sign()) { … … 438 487 439 488 // (-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(); 442 495 return absoluteXor(vm, result, y1); 443 496 } … … 450 503 451 504 // 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 453 508 result = absoluteXor(vm, result, x); 454 return absoluteAddOne(vm, result, SignOption::Signed); 509 scope.release(); 510 return absoluteAddOne(exec, result, SignOption::Signed); 455 511 } 456 512 … … 752 808 } 753 809 754 JSBigInt* JSBigInt::absoluteAdd(VM& vm, JSBigInt* x, JSBigInt* y, bool resultSign) 755 { 810 JSBigInt* JSBigInt::absoluteAdd(ExecState* exec, JSBigInt* x, JSBigInt* y, bool resultSign) 811 { 812 VM& vm = exec->vm(); 813 756 814 if (x->length() < y->length()) 757 return absoluteAdd( vm, y, x, resultSign);815 return absoluteAdd(exec, y, x, resultSign); 758 816 759 817 if (x->isZero()) { … … 765 823 return resultSign == x->sign() ? x : unaryMinus(vm, x); 766 824 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; 769 828 Digit carry = 0; 770 829 unsigned i = 0; … … 807 866 return JSBigInt::createZero(vm); 808 867 809 JSBigInt* result = JSBigInt::createWithLength(vm, x->length()); 868 JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, x->length()); 869 810 870 Digit borrow = 0; 811 871 unsigned i = 0; … … 852 912 if (quotient != nullptr) { 853 913 if (*quotient == nullptr) 854 *quotient = JSBigInt::createWithLength (vm, length);914 *quotient = JSBigInt::createWithLengthUnchecked(vm, length); 855 915 856 916 for (int i = length - 1; i >= 0; i--) { … … 870 930 // interested in one of them. 871 931 // See Knuth, Volume 2, section 4.3.1, Algorithm D. 872 void JSBigInt::absoluteDivWithBigIntDivisor( VM& vm, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder)932 void JSBigInt::absoluteDivWithBigIntDivisor(ExecState* exec, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder) 873 933 { 874 934 ASSERT(divisor->length() >= 2); 875 935 ASSERT(dividend->length() >= divisor->length()); 936 VM& vm = exec->vm(); 937 auto scope = DECLARE_THROW_SCOPE(vm); 876 938 877 939 // The unusual variable names inside this function are consistent with … … 885 947 JSBigInt* q = nullptr; 886 948 if (quotient != nullptr) 887 q = createWithLength (vm, m + 1);949 q = createWithLengthUnchecked(exec->vm(), m + 1); 888 950 889 951 // In each iteration, {qhatv} holds {divisor} * {current quotient digit}. 890 952 // "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()); 892 955 893 956 // D1. … … 899 962 unsigned shift = sizeof(lastDigit) == 8 ? clz64(lastDigit) : clz32(lastDigit); 900 963 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 } 903 968 904 969 // Holds the (continuously updated) remaining part of the dividend, which 905 970 // 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()); 907 973 908 974 // D2. … … 1032 1098 1033 1099 // Always copies the input, even when {shift} == 0. 1034 JSBigInt* JSBigInt::absoluteLeftShiftAlwaysCopy( VM& vm, JSBigInt* x, unsigned shift, LeftShiftMode mode)1100 JSBigInt* JSBigInt::absoluteLeftShiftAlwaysCopy(ExecState* exec, JSBigInt* x, unsigned shift, LeftShiftMode mode) 1035 1101 { 1036 1102 ASSERT(shift < digitBits); … … 1039 1105 unsigned n = x->length(); 1040 1106 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; 1042 1110 1043 1111 if (!shift) { … … 1096 1164 ASSERT(numPairs == std::min(xLength, yLength)); 1097 1165 unsigned resultLength = extraDigits == ExtraDigitsHandling::Copy ? xLength : numPairs; 1098 JSBigInt* result = createWithLength(vm, resultLength); 1099 1166 JSBigInt* result = createWithLengthUnchecked(vm, resultLength); 1100 1167 unsigned i = 0; 1101 1168 for (; i < numPairs; i++) … … 1145 1212 } 1146 1213 1147 JSBigInt* JSBigInt::absoluteAddOne( VM& vm, JSBigInt* x, SignOption signOption)1214 JSBigInt* JSBigInt::absoluteAddOne(ExecState* exec, JSBigInt* x, SignOption signOption) 1148 1215 { 1149 1216 unsigned inputLength = x->length(); … … 1159 1226 1160 1227 unsigned resultLength = inputLength + willOverflow; 1161 JSBigInt* result = createWithLength(vm, resultLength); 1228 JSBigInt* result = tryCreateWithLength(exec, resultLength); 1229 if (!result) 1230 return nullptr; 1162 1231 1163 1232 Digit carry = 1; … … 1173 1242 1174 1243 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 1247 JSBigInt* JSBigInt::absoluteSubOne(ExecState* exec, JSBigInt* x, unsigned resultLength) 1181 1248 { 1182 1249 ASSERT(!x->isZero()); 1183 1250 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); 1185 1256 1186 1257 unsigned length = x->length(); … … 1355 1426 Digit chunk; 1356 1427 absoluteDivWithDigitDivisor(vm, *dividend, chunkDivisor, &rest, chunk); 1357 ASSERT(rest);1358 1359 1428 dividend = &rest; 1360 1429 for (unsigned i = 0; i < chunkChars; i++) { … … 1415 1484 1416 1485 unsigned newLength = nonZeroIndex + 1; 1417 JSBigInt* trimmedBigInt = createWithLength(vm, newLength); 1418 RELEASE_ASSERT(trimmedBigInt); 1486 JSBigInt* trimmedBigInt = createWithLengthUnchecked(vm, newLength); 1419 1487 std::copy(dataStorage(), dataStorage() + newLength, trimmedBigInt->dataStorage()); 1420 1488 … … 1440 1508 unsigned length = (bitsMin + digitBits - 1) / digitBits; 1441 1509 if (length <= maxLength) { 1442 JSBigInt* result = JSBigInt::createWithLength (vm, length);1510 JSBigInt* result = JSBigInt::createWithLengthUnchecked(vm, length); 1443 1511 return result; 1444 1512 } -
trunk/Source/JavaScriptCore/runtime/JSBigInt.h
r238156 r238425 52 52 static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); 53 53 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); 55 56 56 57 static JSBigInt* createFrom(VM&, int32_t value); … … 109 110 ComparisonResult static compareToDouble(JSBigInt* x, double y); 110 111 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); 113 114 static JSBigInt* divide(ExecState*, JSBigInt* x, JSBigInt* y); 114 115 static JSBigInt* remainder(ExecState*, JSBigInt* x, JSBigInt* y); 115 116 static JSBigInt* unaryMinus(VM&, JSBigInt* x); 116 117 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); 120 121 121 122 private: … … 140 141 static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned, JSBigInt* result); 141 142 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); 143 144 144 145 enum class LeftShiftMode { … … 147 148 }; 148 149 149 static JSBigInt* absoluteLeftShiftAlwaysCopy( VM&, JSBigInt* x, unsigned shift, LeftShiftMode);150 static JSBigInt* absoluteLeftShiftAlwaysCopy(ExecState*, JSBigInt* x, unsigned shift, LeftShiftMode); 150 151 static bool productGreaterThan(Digit factor1, Digit factor2, Digit high, Digit low); 151 152 … … 177 178 }; 178 179 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); 181 182 182 183 // Digit arithmetic helpers. … … 204 205 205 206 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); 207 208 static JSBigInt* absoluteSub(VM&, JSBigInt* x, JSBigInt* y, bool resultSign); 208 209 -
trunk/Source/JavaScriptCore/runtime/Operations.cpp
r238156 r238425 70 70 71 71 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 } 74 76 75 77 return throwTypeError(callFrame, scope, "Invalid mix of BigInt and other type in addition."_s); -
trunk/Source/JavaScriptCore/runtime/Operations.h
r238156 r238425 349 349 350 350 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 } 353 355 354 356 return throwTypeError(exec, scope, "Invalid mix of BigInt and other type in subtraction."_s); … … 369 371 370 372 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(); 372 375 return JSBigInt::multiply(state, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); 376 } 373 377 374 378 throwTypeError(state, scope, "Invalid mix of BigInt and other type in multiplication."_s);
Note: See TracChangeset
for help on using the changeset viewer.