Ignore:
Timestamp:
May 30, 2020, 12:46:53 AM (5 years ago)
Author:
[email protected]
Message:

[JSC] JSBigInt allocation should be graceful for OOM
https://bugs.webkit.org/show_bug.cgi?id=212512

Reviewed by Mark Lam.

JSTests:

  • stress/bigint-can-throw-oom.js: Copied from JSTests/stress/get-function-realm-not-doing-recursion.js.

(canThrow):
(foo):
(get foo):

  • stress/get-function-realm-not-doing-recursion.js:

(canThrow):

Source/JavaScriptCore:

This patch allows JSBigInt's storage allocation to fail gracefully if OOM condition happens.
We thread JSGlobalObject* instead of VM& and throw OOM error if storage allocation failed.
We also rename JSGlobalObject* globalObject parameter to JSGlobalObject* nullOrGlobalObjectForOOM
if it can be nullptr.

  • jit/JITOperations.cpp:
  • jsc.cpp:

(functionCreateHeapBigInt):

  • parser/ParserArena.cpp:

(JSC::IdentifierArena::makeBigIntDecimalIdentifier):

  • runtime/BigIntConstructor.cpp:

(JSC::toBigInt):
(JSC::callBigIntConstructor):

  • runtime/BigIntPrototype.cpp:

(JSC::toThisBigIntValue):
(JSC::bigIntProtoFuncToString):
(JSC::bigIntProtoFuncToLocaleString):
(JSC::bigIntProtoFuncValueOf):

  • runtime/CachedTypes.cpp:

(JSC::CachedBigInt::decode const):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/IntlNumberFormatPrototype.cpp:

(JSC::IntlNumberFormatFuncFormat):

  • runtime/JSBigInt.cpp:

(JSC::JSBigInt::createZero):
(JSC::JSBigInt::tryCreateZero):
(JSC::JSBigInt::createWithLength):
(JSC::JSBigInt::tryCreateWithLength):
(JSC::JSBigInt::createFrom):
(JSC::JSBigInt::tryCreateFrom):
(JSC::JSBigInt::createFromImpl):
(JSC::JSBigInt::parseInt):
(JSC::HeapBigIntImpl::toHeapBigInt):
(JSC::Int32BigIntImpl::toHeapBigInt):
(JSC::zeroImpl):
(JSC::JSBigInt::exponentiateImpl):
(JSC::JSBigInt::multiplyImpl):
(JSC::JSBigInt::divideImpl):
(JSC::JSBigInt::copy):
(JSC::JSBigInt::unaryMinusImpl):
(JSC::JSBigInt::unaryMinus):
(JSC::JSBigInt::remainderImpl):
(JSC::JSBigInt::incImpl):
(JSC::JSBigInt::decImpl):
(JSC::JSBigInt::addImpl):
(JSC::JSBigInt::subImpl):
(JSC::JSBigInt::bitwiseAndImpl):
(JSC::JSBigInt::bitwiseOrImpl):
(JSC::JSBigInt::bitwiseXorImpl):
(JSC::JSBigInt::absoluteAdd):
(JSC::JSBigInt::absoluteSub):
(JSC::JSBigInt::absoluteDivWithDigitDivisor):
(JSC::JSBigInt::absoluteDivWithBigIntDivisor):
(JSC::JSBigInt::absoluteLeftShiftAlwaysCopy):
(JSC::JSBigInt::absoluteBitwiseOp):
(JSC::JSBigInt::absoluteAnd):
(JSC::JSBigInt::absoluteOr):
(JSC::JSBigInt::absoluteAndNot):
(JSC::JSBigInt::absoluteXor):
(JSC::JSBigInt::absoluteAddOne):
(JSC::JSBigInt::absoluteSubOne):
(JSC::JSBigInt::leftShiftByAbsolute):
(JSC::JSBigInt::rightShiftByAbsolute):
(JSC::JSBigInt::rightShiftByMaximum):
(JSC::JSBigInt::toStringBasePowerOfTwo):
(JSC::JSBigInt::toStringGeneric):
(JSC::JSBigInt::rightTrim):
(JSC::JSBigInt::tryRightTrim):
(JSC::JSBigInt::allocateFor):
(JSC::JSBigInt::asIntNImpl):
(JSC::JSBigInt::asUintNImpl):
(JSC::JSBigInt::truncateToNBits):
(JSC::JSBigInt::truncateAndSubFromPowerOfTwo):
(JSC::JSBigInt::createWithLengthUnchecked): Deleted.

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

(JSC::JSValue::toThisSlowCase const):

  • runtime/VM.cpp:

(JSC::VM::VM):

Source/WebCore:

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneDeserializer::readBigInt):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.h

    r262012 r262342  
    6666
    6767    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
    68     JS_EXPORT_PRIVATE static JSBigInt* createZero(VM&);
    69     JS_EXPORT_PRIVATE static JSBigInt* tryCreateWithLength(JSGlobalObject*, unsigned length);
    70     static JSBigInt* createWithLengthUnchecked(VM&, unsigned length);
    71 
    72     JS_EXPORT_PRIVATE static JSBigInt* createFrom(VM&, int32_t value);
    73     static JSBigInt* createFrom(VM&, uint32_t value);
    74     static JSBigInt* createFrom(VM&, int64_t value);
    75     static JSBigInt* createFrom(VM&, uint64_t value);
    76     static JSBigInt* createFrom(VM&, bool value);
    77     static JSBigInt* createFrom(VM&, double value);
     68    JS_EXPORT_PRIVATE static JSBigInt* createZero(JSGlobalObject*);
     69    JS_EXPORT_PRIVATE static JSBigInt* tryCreateZero(VM&);
     70    JS_EXPORT_PRIVATE static JSBigInt* tryCreateWithLength(VM&, unsigned length);
     71    JS_EXPORT_PRIVATE static JSBigInt* createWithLength(JSGlobalObject*, unsigned length);
     72
     73    JS_EXPORT_PRIVATE static JSBigInt* createFrom(JSGlobalObject*, int32_t value);
     74    static JSBigInt* tryCreateFrom(VM&, int32_t value);
     75    static JSBigInt* createFrom(JSGlobalObject*, uint32_t value);
     76    static JSBigInt* createFrom(JSGlobalObject*, int64_t value);
     77    static JSBigInt* createFrom(JSGlobalObject*, uint64_t value);
     78    static JSBigInt* createFrom(JSGlobalObject*, bool value);
     79    static JSBigInt* createFrom(JSGlobalObject*, double value);
     80
     81    static JSBigInt* createFrom(JSGlobalObject*, VM&, int32_t value);
    7882
    7983    static size_t offsetOfLength()
     
    9195    unsigned length() const { return m_length; }
    9296
    93     static JSValue makeHeapBigIntOrBigInt32(VM& vm, int64_t value)
     97    static JSValue makeHeapBigIntOrBigInt32(JSGlobalObject* globalObject, int64_t value)
    9498    {
    9599#if USE(BIGINT32)
     
    97101            return jsBigInt32(static_cast<int32_t>(value));
    98102#endif
    99         return JSBigInt::createFrom(vm, value);
    100     }
    101 
    102     static JSValue makeHeapBigIntOrBigInt32(VM& vm, double value)
     103        return JSBigInt::createFrom(globalObject, value);
     104    }
     105
     106    static JSValue makeHeapBigIntOrBigInt32(JSGlobalObject* globalObject, double value)
    103107    {
    104108        ASSERT(isInteger(value));
    105109        if (std::abs(value) <= maxSafeInteger())
    106             return makeHeapBigIntOrBigInt32(vm, static_cast<int64_t>(value));
    107         return JSBigInt::createFrom(vm, value);
     110            return makeHeapBigIntOrBigInt32(globalObject, static_cast<int64_t>(value));
     111        return JSBigInt::createFrom(globalObject, value);
    108112    }
    109113
     
    159163    ComparisonResult static compareToDouble(JSBigInt* x, double y);
    160164
    161     ALWAYS_INLINE static JSValue asInt32OrHeapCell(VM& vm, int64_t value)
     165    ALWAYS_INLINE static JSValue asInt32OrHeapCell(JSGlobalObject* globalObject, int64_t value)
    162166    {
    163167#if USE(BIGINT32)
     
    165169            return jsBigInt32(static_cast<int32_t>(value));
    166170#endif
    167         return createFrom(vm, value);
    168     }
    169     ALWAYS_INLINE static JSValue asInt32OrHeapCell(JSGlobalObject* globalObject, int64_t value)
    170     {
    171         return asInt32OrHeapCell(globalObject->vm(), value);
     171        return createFrom(globalObject, value);
    172172    }
    173173
     
    185185    };
    186186private:
     187    static JSBigInt* createWithLength(JSGlobalObject*, VM&, unsigned length);
     188    static JSBigInt* createZero(JSGlobalObject*, VM&);
    187189
    188190    template <typename BigIntImpl1, typename BigIntImpl2>
     
    211213
    212214    template <typename BigIntImpl>
    213     static ImplResult unaryMinusImpl(VM&, BigIntImpl x);
     215    static ImplResult unaryMinusImpl(JSGlobalObject*, BigIntImpl x);
    214216
    215217    template <typename BigIntImpl1, typename BigIntImpl2>
     
    296298    {
    297299        if (!y) {
    298             auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
     300            auto scope = DECLARE_THROW_SCOPE(getVM(globalObject));
    299301            throwRangeError(globalObject, scope, "0 is an invalid divisor value."_s);
    300302            return JSValue();
     
    311313    {
    312314        if (!y) {
    313             auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
     315            auto scope = DECLARE_THROW_SCOPE(getVM(globalObject));
    314316            throwRangeError(globalObject, scope, "0 is an invalid divisor value."_s);
    315317            return JSValue();
     
    319321#endif
    320322
    321     static JSValue unaryMinus(VM&, JSBigInt* x);
    322 #if USE(BIGINT32)
    323     static JSValue unaryMinus(VM& vm, int32_t x)
    324     {
    325         return asInt32OrHeapCell(vm, -static_cast<int64_t>(x));
     323    static JSValue unaryMinus(JSGlobalObject*, JSBigInt* x);
     324#if USE(BIGINT32)
     325    static JSValue unaryMinus(JSGlobalObject* globalObject, int32_t x)
     326    {
     327        return asInt32OrHeapCell(globalObject, -static_cast<int64_t>(x));
    326328    }
    327329#endif
     
    424426    Digit digit(unsigned);
    425427    void setDigit(unsigned, Digit); // Use only when initializing.
    426     JS_EXPORT_PRIVATE JSBigInt* rightTrim(VM&);
     428    JS_EXPORT_PRIVATE JSBigInt* rightTrim(JSGlobalObject*);
     429    JS_EXPORT_PRIVATE JSBigInt* tryRightTrim(VM&);
    427430
    428431private:
    429432    JSBigInt(VM&, Structure*, Digit*, unsigned length);
    430433
    431     static JSBigInt* createFromImpl(VM&, uint64_t value, bool sign);
     434    JSBigInt* rightTrim(JSGlobalObject*, VM&);
     435
     436    static JSBigInt* createFromImpl(JSGlobalObject*, uint64_t value, bool sign);
    432437
    433438    static constexpr unsigned bitsPerByte = 8;
     
    455460    static ComparisonResult absoluteCompare(BigIntImpl1 x, BigIntImpl2 y);
    456461    template <typename BigIntImpl>
    457     static void absoluteDivWithDigitDivisor(VM&, BigIntImpl x, Digit divisor, JSBigInt** quotient, Digit& remainder);
     462    static bool absoluteDivWithDigitDivisor(JSGlobalObject*, VM&, BigIntImpl x, Digit divisor, JSBigInt** quotient, Digit& remainder);
    458463    template <typename BigIntImpl>
    459464    static void internalMultiplyAdd(BigIntImpl source, Digit factor, Digit summand, unsigned, JSBigInt* result);
     
    490495
    491496    template<typename BigIntImpl1, typename BigIntImpl2, typename BitwiseOp>
    492     static JSBigInt* absoluteBitwiseOp(VM&, BigIntImpl1 x, BigIntImpl2 y, ExtraDigitsHandling, BitwiseOp&&);
    493 
    494     template <typename BigIntImpl1, typename BigIntImpl2>
    495     static JSBigInt* absoluteAnd(VM&, BigIntImpl1 x, BigIntImpl2 y);
    496     template <typename BigIntImpl1, typename BigIntImpl2>
    497     static JSBigInt* absoluteOr(VM&, BigIntImpl1 x, BigIntImpl2 y);
    498     template <typename BigIntImpl1, typename BigIntImpl2>
    499     static JSBigInt* absoluteAndNot(VM&, BigIntImpl1 x, BigIntImpl2 y);
    500     template <typename BigIntImpl1, typename BigIntImpl2>
    501     static JSBigInt* absoluteXor(VM&, BigIntImpl1 x, BigIntImpl2 y);
     497    static JSBigInt* absoluteBitwiseOp(JSGlobalObject*, BigIntImpl1 x, BigIntImpl2 y, ExtraDigitsHandling, BitwiseOp&&);
     498
     499    template <typename BigIntImpl1, typename BigIntImpl2>
     500    static JSBigInt* absoluteAnd(JSGlobalObject*, BigIntImpl1 x, BigIntImpl2 y);
     501    template <typename BigIntImpl1, typename BigIntImpl2>
     502    static JSBigInt* absoluteOr(JSGlobalObject*, BigIntImpl1 x, BigIntImpl2 y);
     503    template <typename BigIntImpl1, typename BigIntImpl2>
     504    static JSBigInt* absoluteAndNot(JSGlobalObject*, BigIntImpl1 x, BigIntImpl2 y);
     505    template <typename BigIntImpl1, typename BigIntImpl2>
     506    static JSBigInt* absoluteXor(JSGlobalObject*, BigIntImpl1 x, BigIntImpl2 y);
    502507
    503508    enum class SignOption {
     
    536541
    537542    template <typename BigIntImpl>
    538     static JSBigInt* copy(VM&, BigIntImpl x);
     543    static JSBigInt* copy(JSGlobalObject*, BigIntImpl x);
    539544
    540545    void inplaceMultiplyAdd(Digit multiplier, Digit part);
     
    542547    static ImplResult absoluteAdd(JSGlobalObject*, BigIntImpl1 x, BigIntImpl2 y, bool resultSign);
    543548    template <typename BigIntImpl1, typename BigIntImpl2>
    544     static ImplResult absoluteSub(VM&, BigIntImpl1 x, BigIntImpl2 y, bool resultSign);
     549    static ImplResult absoluteSub(JSGlobalObject*, BigIntImpl1 x, BigIntImpl2 y, bool resultSign);
    545550
    546551    template <typename BigIntImpl1, typename BigIntImpl2>
     
    549554    static ImplResult rightShiftByAbsolute(JSGlobalObject*, BigIntImpl1 x, BigIntImpl2 y);
    550555
    551     static ImplResult rightShiftByMaximum(VM&, bool sign);
     556    static ImplResult rightShiftByMaximum(JSGlobalObject*, bool sign);
    552557
    553558    template <typename BigIntImpl>
     
    559564    static ImplResult asUintNImpl(JSGlobalObject*, uint64_t, BigIntImpl);
    560565    template <typename BigIntImpl>
    561     static ImplResult truncateToNBits(VM&, int32_t, BigIntImpl);
    562     template <typename BigIntImpl>
    563     static ImplResult truncateAndSubFromPowerOfTwo(VM&, int32_t, BigIntImpl, bool resultSign);
     566    static ImplResult truncateToNBits(JSGlobalObject*, int32_t, BigIntImpl);
     567    template <typename BigIntImpl>
     568    static ImplResult truncateAndSubFromPowerOfTwo(JSGlobalObject*, int32_t, BigIntImpl, bool resultSign);
    564569
    565570    inline static size_t offsetOfData()
Note: See TracChangeset for help on using the changeset viewer.