Changeset 209011 in webkit


Ignore:
Timestamp:
Nov 28, 2016 1:26:10 PM (7 years ago)
Author:
mark.lam@apple.com
Message:

Fix exception scope verification failures in ArrayConstructor.cpp and ArrayPrototype.cpp.
https://bugs.webkit.org/show_bug.cgi?id=164972

Reviewed by Geoffrey Garen.

  • runtime/ArrayConstructor.cpp:

(JSC::constructArrayWithSizeQuirk):

  • runtime/ArrayPrototype.cpp:

(JSC::getProperty):
(JSC::putLength):
(JSC::speciesWatchpointsValid):
(JSC::speciesConstructArray):
(JSC::shift):
(JSC::unshift):
(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncToLocaleString):
(JSC::slowJoin):
(JSC::fastJoin):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncReverse):
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncSlice):
(JSC::arrayProtoFuncSplice):
(JSC::arrayProtoFuncUnShift):
(JSC::arrayProtoFuncIndexOf):
(JSC::arrayProtoFuncLastIndexOf):
(JSC::concatAppendOne):
(JSC::arrayProtoPrivateFuncConcatMemcpy):
(JSC::ArrayPrototype::attemptToInitializeSpeciesWatchpoint):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r209007 r209011  
     12016-11-24  Mark Lam  <mark.lam@apple.com>
     2
     3        Fix exception scope verification failures in ArrayConstructor.cpp and ArrayPrototype.cpp.
     4        https://bugs.webkit.org/show_bug.cgi?id=164972
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * runtime/ArrayConstructor.cpp:
     9        (JSC::constructArrayWithSizeQuirk):
     10        * runtime/ArrayPrototype.cpp:
     11        (JSC::getProperty):
     12        (JSC::putLength):
     13        (JSC::speciesWatchpointsValid):
     14        (JSC::speciesConstructArray):
     15        (JSC::shift):
     16        (JSC::unshift):
     17        (JSC::arrayProtoFuncToString):
     18        (JSC::arrayProtoFuncToLocaleString):
     19        (JSC::slowJoin):
     20        (JSC::fastJoin):
     21        (JSC::arrayProtoFuncJoin):
     22        (JSC::arrayProtoFuncPop):
     23        (JSC::arrayProtoFuncPush):
     24        (JSC::arrayProtoFuncReverse):
     25        (JSC::arrayProtoFuncShift):
     26        (JSC::arrayProtoFuncSlice):
     27        (JSC::arrayProtoFuncSplice):
     28        (JSC::arrayProtoFuncUnShift):
     29        (JSC::arrayProtoFuncIndexOf):
     30        (JSC::arrayProtoFuncLastIndexOf):
     31        (JSC::concatAppendOne):
     32        (JSC::arrayProtoPrivateFuncConcatMemcpy):
     33        (JSC::ArrayPrototype::attemptToInitializeSpeciesWatchpoint):
     34
    1352016-11-28  Mark Lam  <mark.lam@apple.com>
    236
  • trunk/Source/JavaScriptCore/runtime/ArrayConstructor.cpp

    r206065 r209011  
    7171    VM& vm = exec->vm();
    7272    auto scope = DECLARE_THROW_SCOPE(vm);
    73     if (!length.isNumber())
     73    if (!length.isNumber()) {
     74        scope.release();
    7475        return constructArrayNegativeIndexed(exec, profile, globalObject, &length, 1, newTarget);
     76    }
    7577   
    7678    uint32_t n = length.toUInt32(exec);
    7779    if (n != length.toNumber(exec))
    7880        return throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer.")));
     81    scope.release();
    7982    return constructEmptyArray(exec, profile, globalObject, n, newTarget);
    8083}
  • trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp

    r208767 r209011  
    150150static ALWAYS_INLINE JSValue getProperty(ExecState* exec, JSObject* object, unsigned index)
    151151{
     152    VM& vm = exec->vm();
     153    auto scope = DECLARE_THROW_SCOPE(vm);
     154   
    152155    if (JSValue result = object->tryGetIndexQuickly(index))
    153156        return result;
     
    157160    // somewhere in the prototype chain.
    158161    PropertySlot slot(object, PropertySlot::InternalMethodType::HasProperty);
    159     if (!object->getPropertySlot(exec, index, slot))
    160         return JSValue();
    161     if (UNLIKELY(slot.isTaintedByOpaqueObject()))
     162    bool hasProperty = object->getPropertySlot(exec, index, slot);
     163    ASSERT(!scope.exception() || !hasProperty);
     164    if (!hasProperty)
     165        return { };
     166    if (UNLIKELY(slot.isTaintedByOpaqueObject())) {
     167        scope.release();
    162168        return object->get(exec, index);
     169    }
     170    scope.release();
    163171    return slot.getValue(exec, index);
    164172}
     
    167175{
    168176    PutPropertySlot slot(obj);
    169     return obj->methodTable()->put(obj, exec, vm.propertyNames->length, value, slot);
     177    return obj->methodTable(vm)->put(obj, exec, vm.propertyNames->length, value, slot);
    170178}
    171179
     
    186194inline bool speciesWatchpointsValid(ExecState* exec, JSObject* thisObject)
    187195{
     196    VM& vm = exec->vm();
     197    auto scope = DECLARE_THROW_SCOPE(vm);
     198
    188199    ArrayPrototype* arrayPrototype = thisObject->globalObject()->arrayPrototype();
    189200    ArrayPrototype::SpeciesWatchpointStatus status = arrayPrototype->speciesWatchpointStatus();
    190     if (UNLIKELY(status == ArrayPrototype::SpeciesWatchpointStatus::Uninitialized))
     201    if (UNLIKELY(status == ArrayPrototype::SpeciesWatchpointStatus::Uninitialized)) {
    191202        status = arrayPrototype->attemptToInitializeSpeciesWatchpoint(exec);
     203        RETURN_IF_EXCEPTION(scope, false);
     204    }
    192205    ASSERT(status != ArrayPrototype::SpeciesWatchpointStatus::Uninitialized);
    193206    return !thisObject->hasCustomProperties()
     
    213226    // ECMA 9.4.2.3: https://tc39.github.io/ecma262/#sec-arrayspeciescreate
    214227    JSValue constructor = jsUndefined();
    215     if (LIKELY(isArray(exec, thisObject))) {
     228    bool thisIsArray = isArray(exec, thisObject);
     229    RETURN_IF_EXCEPTION(scope, exceptionResult());
     230    if (LIKELY(thisIsArray)) {
    216231        // Fast path in the normal case where the user has not set an own constructor and the Array.prototype.constructor is normal.
    217232        // We need prototype check for subclasses of Array, which are Array objects but have a different prototype by default.
    218         if (LIKELY(speciesWatchpointsValid(exec, thisObject)))
     233        bool isValid = speciesWatchpointsValid(exec, thisObject);
     234        RETURN_IF_EXCEPTION(scope, exceptionResult());
     235        if (LIKELY(isValid))
    219236            return std::make_pair(SpeciesConstructResult::FastPath, nullptr);
    220237
    221         constructor = thisObject->get(exec, exec->propertyNames().constructor);
     238        constructor = thisObject->get(exec, vm.propertyNames->constructor);
    222239        RETURN_IF_EXCEPTION(scope, exceptionResult());
    223240        if (constructor.isConstructor()) {
     
    227244        }
    228245        if (constructor.isObject()) {
    229             constructor = constructor.get(exec, exec->propertyNames().speciesSymbol);
     246            constructor = constructor.get(exec, vm.propertyNames->speciesSymbol);
    230247            RETURN_IF_EXCEPTION(scope, exceptionResult());
    231248            if (constructor.isNull())
     
    295312        unsigned from = k + currentCount;
    296313        unsigned to = k + resultCount;
    297         if (JSValue value = getProperty(exec, thisObj, from)) {
    298             RETURN_IF_EXCEPTION(scope, void());
     314        JSValue value = getProperty(exec, thisObj, from);
     315        RETURN_IF_EXCEPTION(scope, void());
     316        if (value) {
    299317            thisObj->putByIndexInline(exec, to, value, true);
    300318            RETURN_IF_EXCEPTION(scope, void());
    301         } else if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to)) {
    302             throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
    303             return;
     319        } else {
     320            bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to);
     321            RETURN_IF_EXCEPTION(scope, void());
     322            if (!success) {
     323                throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     324                return;
     325            }
    304326        }
    305327    }
    306328    for (unsigned k = length; k > length - count; --k) {
    307         if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, k - 1)) {
     329        bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, k - 1);
     330        RETURN_IF_EXCEPTION(scope, void());
     331        if (!success) {
    308332            throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
    309333            return;
     
    332356    if (isJSArray(thisObj)) {
    333357        JSArray* array = asArray(thisObj);
    334         if (array->length() == length && array->unshiftCount<shiftCountMode>(exec, header, count))
    335             return;
     358        if (array->length() == length) {
     359            bool handled = array->unshiftCount<shiftCountMode>(exec, header, count);
     360            ASSERT(!scope.exception() || handled);
     361            if (handled)
     362                return;
     363        }
    336364    }
    337365
     
    339367        unsigned from = k + currentCount - 1;
    340368        unsigned to = k + resultCount - 1;
    341         if (JSValue value = getProperty(exec, thisObj, from)) {
     369        JSValue value = getProperty(exec, thisObj, from);
     370        RETURN_IF_EXCEPTION(scope, void());
     371        if (value) {
     372            thisObj->putByIndexInline(exec, to, value, true);
    342373            RETURN_IF_EXCEPTION(scope, void());
    343             thisObj->putByIndexInline(exec, to, value, true);
    344         } else if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to)) {
    345             throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
    346             return;
    347         }
    348         RETURN_IF_EXCEPTION(scope, void());
     374        } else {
     375            bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to);
     376            RETURN_IF_EXCEPTION(scope, void());
     377            if (UNLIKELY(!success)) {
     378                throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     379                return;
     380            }
     381        }
    349382    }
    350383}
     
    361394   
    362395    // 2. Let func be the result of calling the [[Get]] internal method of array with argument "join".
    363     JSValue function = JSValue(thisObject).get(exec, exec->propertyNames().join);
     396    JSValue function = JSValue(thisObject).get(exec, vm.propertyNames->join);
    364397    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    365398
     
    379412
    380413    // 4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.
    381     if (!isJSArray(thisObject) || callType != CallType::Host || callData.native.function != arrayProtoFuncJoin)
     414    if (!isJSArray(thisObject) || callType != CallType::Host || callData.native.function != arrayProtoFuncJoin) {
     415        scope.release();
    382416        return JSValue::encode(call(exec, function, callType, callData, thisObject, exec->emptyList()));
     417    }
    383418
    384419    ASSERT(isJSArray(thisValue));
     
    388423
    389424    StringRecursionChecker checker(exec, thisArray);
     425    ASSERT(!scope.exception() || checker.earlyReturnValue());
    390426    if (JSValue earlyReturnValue = checker.earlyReturnValue())
    391427        return JSValue::encode(earlyReturnValue);
     
    404440    }
    405441
     442    scope.release();
    406443    return JSValue::encode(joiner.join(*exec));
    407444}
     
    420457
    421458    StringRecursionChecker checker(exec, thisObject);
     459    ASSERT(!scope.exception() || checker.earlyReturnValue());
    422460    if (JSValue earlyReturnValue = checker.earlyReturnValue())
    423461        return JSValue::encode(earlyReturnValue);
     
    434472            element = jsEmptyString(exec);
    435473        else {
    436             JSValue conversionFunction = element.get(exec, exec->propertyNames().toLocaleString);
     474            JSValue conversionFunction = element.get(exec, vm.propertyNames->toLocaleString);
    437475            RETURN_IF_EXCEPTION(scope, encodedJSValue());
    438476            CallData callData;
     
    452490        if (element.isUndefinedOrNull())
    453491            continue;
    454         JSValue conversionFunction = element.get(exec, exec->propertyNames().toLocaleString);
     492        JSValue conversionFunction = element.get(exec, vm.propertyNames->toLocaleString);
    455493        RETURN_IF_EXCEPTION(scope, encodedJSValue());
    456494        CallData callData;
     
    465503#endif // !ENABLE(INTL)
    466504
     505    scope.release();
    467506    return JSValue::encode(stringJoiner.join(*exec));
    468507}
     
    504543    // 6. Let element0 be Get(O, "0").
    505544    JSValue element0 = thisObject->getIndex(&exec, 0);
    506     RETURN_IF_EXCEPTION(scope, JSValue());
     545    RETURN_IF_EXCEPTION(scope, { });
    507546
    508547    // 7. If element0 is undefined or null, let R be the empty String; otherwise, let R be ? ToString(element0).
     
    512551    else
    513552        r = element0.toString(&exec);
    514     RETURN_IF_EXCEPTION(scope, JSValue());
     553    RETURN_IF_EXCEPTION(scope, { });
    515554
    516555    // 8. Let k be 1.
     
    520559        // b. Let element be ? Get(O, ! ToString(k)).
    521560        JSValue element = thisObject->get(&exec, Identifier::fromString(&exec, AtomicString::number(k)));
    522         RETURN_IF_EXCEPTION(scope, JSValue());
     561        RETURN_IF_EXCEPTION(scope, { });
    523562
    524563        // c. If element is undefined or null, let next be the empty String; otherwise, let next be ? ToString(element).
     
    530569        } else
    531570            next = element.toString(&exec);
    532         RETURN_IF_EXCEPTION(scope, JSValue());
     571        RETURN_IF_EXCEPTION(scope, { });
    533572
    534573        // a. Let S be the String value produced by concatenating R and sep.
    535574        // d. Let R be a String value produced by concatenating S and next.
    536575        r = jsString(&exec, r, separator, next);
    537         RETURN_IF_EXCEPTION(scope, JSValue());
     576        RETURN_IF_EXCEPTION(scope, { });
    538577    }
    539578    // 10. Return R.
     
    566605            break;
    567606        JSStringJoiner joiner(state, separator, length);
    568         RETURN_IF_EXCEPTION(scope, JSValue());
     607        RETURN_IF_EXCEPTION(scope, { });
    569608        auto data = butterfly.contiguous().data();
    570609        bool holesKnownToBeOK = false;
     
    582621            }
    583622        }
     623        scope.release();
    584624        return joiner.join(state);
    585625    }
     
    589629            break;
    590630        JSStringJoiner joiner(state, separator, length);
    591         RETURN_IF_EXCEPTION(scope, JSValue());
     631        RETURN_IF_EXCEPTION(scope, { });
    592632        auto data = butterfly.contiguousDouble().data();
    593633        bool holesKnownToBeOK = false;
     
    605645            }
    606646        }
     647        scope.release();
    607648        return joiner.join(state);
    608649    }
     
    611652generalCase:
    612653    JSStringJoiner joiner(state, separator, length);
    613     RETURN_IF_EXCEPTION(scope, JSValue());
     654    RETURN_IF_EXCEPTION(scope, { });
    614655    for (unsigned i = 0; i < length; ++i) {
    615656        JSValue element = thisObject->getIndex(&state, i);
    616         RETURN_IF_EXCEPTION(scope, JSValue());
     657        RETURN_IF_EXCEPTION(scope, { });
    617658        joiner.append(state, element);
    618         RETURN_IF_EXCEPTION(scope, JSValue());
    619     }
     659        RETURN_IF_EXCEPTION(scope, { });
     660    }
     661    scope.release();
    620662    return joiner.join(state);
    621663}
     
    628670    // 1. Let O be ? ToObject(this value).
    629671    JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    630     if (!thisObject)
    631         return JSValue::encode(JSValue());
     672    ASSERT(!!scope.exception() == !thisObject);
     673    if (UNLIKELY(!thisObject))
     674        return encodedJSValue();
    632675
    633676    StringRecursionChecker checker(exec, thisObject);
     677    ASSERT(!scope.exception() || checker.earlyReturnValue());
    634678    if (JSValue earlyReturnValue = checker.earlyReturnValue())
    635679        return JSValue::encode(earlyReturnValue);
     
    650694            RETURN_IF_EXCEPTION(scope, encodedJSValue());
    651695
     696            scope.release();
    652697            return JSValue::encode(slowJoin(*exec, thisObject, jsSeparator, length64));
    653698        }
     
    655700        unsigned unsignedLength = static_cast<unsigned>(length);
    656701        ASSERT(static_cast<double>(unsignedLength) == length);
     702
     703        scope.release();
    657704        return JSValue::encode(fastJoin(*exec, thisObject, { &comma, 1 }, unsignedLength));
    658705    }
     
    665712        uint64_t length64 = static_cast<uint64_t>(length);
    666713        ASSERT(static_cast<double>(length64) == length);
     714
     715        scope.release();
    667716        return JSValue::encode(slowJoin(*exec, thisObject, jsSeparator, length64));
    668717    }
     
    682731    JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
    683732
    684     if (isJSArray(thisValue))
     733    if (isJSArray(thisValue)) {
     734        scope.release();
    685735        return JSValue::encode(asArray(thisValue)->pop(exec));
     736    }
    686737
    687738    JSObject* thisObj = thisValue.toObject(exec);
    688     if (!thisObj)
    689         return JSValue::encode(JSValue());
     739    ASSERT(!!scope.exception() == !thisObj);
     740    if (UNLIKELY(!thisObj))
     741        return encodedJSValue();
    690742    unsigned length = getLength(exec, thisObj);
    691743    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    692744
    693     JSValue result;
    694745    if (length == 0) {
     746        scope.release();
    695747        putLength(exec, vm, thisObj, jsNumber(length));
    696         result = jsUndefined();
    697     } else {
    698         result = thisObj->get(exec, length - 1);
    699         RETURN_IF_EXCEPTION(scope, encodedJSValue());
    700         if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, length - 1)) {
    701             throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
    702             return JSValue::encode(jsUndefined());
    703         }
    704         putLength(exec, vm, thisObj, jsNumber(length - 1));
    705     }
     748        return JSValue::encode(jsUndefined());
     749    }
     750
     751    JSValue result = thisObj->get(exec, length - 1);
     752    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     753    bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, length - 1);
     754    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     755    if (UNLIKELY(!success)) {
     756        throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     757        return encodedJSValue();
     758    }
     759    scope.release();
     760    putLength(exec, vm, thisObj, jsNumber(length - 1));
    706761    return JSValue::encode(result);
    707762}
     
    715770    if (isJSArray(thisValue) && exec->argumentCount() == 1) {
    716771        JSArray* array = asArray(thisValue);
     772        scope.release();
    717773        array->push(exec, exec->uncheckedArgument(0));
    718774        return JSValue::encode(jsNumber(array->length()));
     
    720776   
    721777    JSObject* thisObj = thisValue.toObject(exec);
    722     if (!thisObj)
    723         return JSValue::encode(JSValue());
     778    ASSERT(!!scope.exception() == !thisObj);
     779    if (UNLIKELY(!thisObj))
     780        return encodedJSValue();
    724781    unsigned length = getLength(exec, thisObj);
    725782    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     
    728785        // Check for integer overflow; where safe we can do a fast put by index.
    729786        if (length + n >= length)
    730             thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->uncheckedArgument(n), true);
     787            thisObj->methodTable(vm)->putByIndex(thisObj, exec, length + n, exec->uncheckedArgument(n), true);
    731788        else {
    732789            PutPropertySlot slot(thisObj);
    733790            Identifier propertyName = Identifier::fromString(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toWTFString(exec));
    734             thisObj->methodTable()->put(thisObj, exec, propertyName, exec->uncheckedArgument(n), slot);
     791            thisObj->methodTable(vm)->put(thisObj, exec, propertyName, exec->uncheckedArgument(n), slot);
    735792        }
    736793        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     
    738795   
    739796    JSValue newLength(static_cast<int64_t>(length) + static_cast<int64_t>(exec->argumentCount()));
     797    scope.release();
    740798    putLength(exec, vm, thisObj, newLength);
    741799    return JSValue::encode(newLength);
     
    748806
    749807    JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    750     if (!thisObject)
    751         return JSValue::encode(JSValue());
     808    ASSERT(!!scope.exception() == !thisObject);
     809    if (UNLIKELY(!thisObject))
     810        return encodedJSValue();
    752811
    753812    unsigned length = getLength(exec, thisObject);
     
    810869            thisObject->putByIndexInline(exec, lower, upperValue, true);
    811870            RETURN_IF_EXCEPTION(scope, encodedJSValue());
    812         } else if (!thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, lower)) {
    813             if (!scope.exception())
     871        } else {
     872            bool success = thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, lower);
     873            RETURN_IF_EXCEPTION(scope, encodedJSValue());
     874            if (UNLIKELY(!success)) {
    814875                throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
    815             return JSValue::encode(JSValue());
     876                return encodedJSValue();
     877            }
    816878        }
    817879
     
    819881            thisObject->putByIndexInline(exec, upper, lowerValue, true);
    820882            RETURN_IF_EXCEPTION(scope, encodedJSValue());
    821         } else if (!thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, upper)) {
    822             if (!scope.exception())
     883        } else {
     884            bool success = thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, upper);
     885            RETURN_IF_EXCEPTION(scope, encodedJSValue());
     886            if (UNLIKELY(!success)) {
    823887                throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
    824             return JSValue::encode(JSValue());
     888                return encodedJSValue();
     889            }
    825890        }
    826891    }
     
    833898    auto scope = DECLARE_THROW_SCOPE(vm);
    834899    JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    835     if (!thisObj)
    836         return JSValue::encode(JSValue());
     900    ASSERT(!!scope.exception() == !thisObj);
     901    if (UNLIKELY(!thisObj))
     902        return encodedJSValue();
    837903    unsigned length = getLength(exec, thisObj);
    838904    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    839905
    840     JSValue result;
    841906    if (length == 0) {
     907        scope.release();
    842908        putLength(exec, vm, thisObj, jsNumber(length));
    843         result = jsUndefined();
    844     } else {
    845         result = thisObj->getIndex(exec, 0);
    846         shift<JSArray::ShiftCountForShift>(exec, thisObj, 0, 1, 0, length);
    847         RETURN_IF_EXCEPTION(scope, encodedJSValue());
    848         putLength(exec, vm, thisObj, jsNumber(length - 1));
    849     }
     909        return JSValue::encode(jsUndefined());
     910    }
     911
     912    JSValue result = thisObj->getIndex(exec, 0);
     913    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     914    shift<JSArray::ShiftCountForShift>(exec, thisObj, 0, 1, 0, length);
     915    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     916    scope.release();
     917    putLength(exec, vm, thisObj, jsNumber(length - 1));
    850918    return JSValue::encode(result);
    851919}
     
    857925    auto scope = DECLARE_THROW_SCOPE(vm);
    858926    JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    859     if (!thisObj)
    860         return JSValue::encode(JSValue());
     927    ASSERT(!!scope.exception() == !thisObj);
     928    if (UNLIKELY(!thisObj))
     929        return encodedJSValue();
    861930    unsigned length = getLength(exec, thisObj);
    862931    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    863932
    864933    unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
     934    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    865935    unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
     936    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    866937
    867938    std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, end - begin);
    868939    // We can only get an exception if we call some user function.
     940    ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
    869941    if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception))
    870         return JSValue::encode(jsUndefined());
    871 
    872     if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj))) {
     942        return encodedJSValue();
     943
     944    bool okToDoFastPath = speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj);
     945    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     946    if (LIKELY(okToDoFastPath)) {
    873947        if (JSArray* result = asArray(thisObj)->fastSlice(*exec, begin, end - begin))
    874948            return JSValue::encode(result);
     
    887961        JSValue v = getProperty(exec, thisObj, k);
    888962        RETURN_IF_EXCEPTION(scope, encodedJSValue());
    889         if (v)
     963        if (v) {
    890964            result->putDirectIndex(exec, n, v, 0, PutDirectIndexShouldThrow);
     965            RETURN_IF_EXCEPTION(scope, encodedJSValue());
     966        }
    891967    }
    892968    scope.release();
     
    903979
    904980    JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    905     if (!thisObj)
    906         return JSValue::encode(JSValue());
     981    ASSERT(!!scope.exception() == !thisObj);
     982    if (UNLIKELY(!thisObj))
     983        return encodedJSValue();
    907984    unsigned length = getLength(exec, thisObj);
    908985    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     
    910987    if (!exec->argumentCount()) {
    911988        std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, 0);
    912         if (speciesResult.first == SpeciesConstructResult::Exception)
    913             return JSValue::encode(jsUndefined());
     989        ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
     990        if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception))
     991            return encodedJSValue();
    914992
    915993        JSObject* result;
     
    9291007
    9301008    unsigned actualStart = argumentClampedIndexFromStartOrEnd(exec, 0, length);
     1009    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    9311010
    9321011    unsigned actualDeleteCount = length - actualStart;
    9331012    if (exec->argumentCount() > 1) {
    9341013        double deleteCount = exec->uncheckedArgument(1).toInteger(exec);
     1014        RETURN_IF_EXCEPTION(scope, encodedJSValue());
    9351015        if (deleteCount < 0)
    9361016            actualDeleteCount = 0;
     
    9421022
    9431023    std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, actualDeleteCount);
     1024    ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
    9441025    if (speciesResult.first == SpeciesConstructResult::Exception)
    9451026        return JSValue::encode(jsUndefined());
    9461027
    9471028    JSObject* result = nullptr;
    948     if (speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj))
     1029    bool okToDoFastPath = speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj);
     1030    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     1031    if (LIKELY(okToDoFastPath))
    9491032        result = asArray(thisObj)->fastSlice(*exec, actualStart, actualDeleteCount);
    9501033
     
    10011084
    10021085    JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    1003     if (!thisObj)
    1004         return JSValue::encode(JSValue());
     1086    ASSERT(!!scope.exception() == !thisObj);
     1087    if (UNLIKELY(!thisObj))
     1088        return encodedJSValue();
    10051089    unsigned length = getLength(exec, thisObj);
    10061090    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     
    10161100    }
    10171101    JSValue result = jsNumber(length + nrArgs);
     1102    scope.release();
    10181103    putLength(exec, vm, thisObj, result);
    10191104    return JSValue::encode(result);
     
    10271112    // 15.4.4.14
    10281113    JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    1029     if (!thisObj)
    1030         return JSValue::encode(JSValue());
     1114    ASSERT(!!scope.exception() == !thisObj);
     1115    if (UNLIKELY(!thisObj))
     1116        return encodedJSValue();
    10311117    unsigned length = getLength(exec, thisObj);
    10321118    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     
    10541140    // 15.4.4.15
    10551141    JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    1056     if (!thisObj)
    1057         return JSValue::encode(JSValue());
     1142    ASSERT(!!scope.exception() == !thisObj);
     1143    if (UNLIKELY(!thisObj))
     1144        return encodedJSValue();
    10581145    unsigned length = getLength(exec, thisObj);
    1059     if (!length)
     1146    if (UNLIKELY(scope.exception()) || !length)
    10601147        return JSValue::encode(jsNumber(-1));
    10611148
     
    11321219        return JSValue::encode(throwOutOfMemoryError(exec, scope));
    11331220
    1134     if (!result->appendMemcpy(exec, vm, 0, first)) {
    1135         if (!moveElements(exec, vm, result, 0, first, firstArraySize)) {
    1136             ASSERT(scope.exception());
    1137             return JSValue::encode(JSValue());
    1138         }
    1139     }
    1140 
     1221    bool success = result->appendMemcpy(exec, vm, 0, first);
     1222    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     1223    if (!success) {
     1224        bool success = moveElements(exec, vm, result, 0, first, firstArraySize);
     1225        ASSERT(!scope.exception() == success);
     1226        if (UNLIKELY(!success))
     1227            return encodedJSValue();
     1228    }
     1229
     1230    scope.release();
    11411231    result->putDirectIndex(exec, firstArraySize, second);
    11421232    return JSValue::encode(result);
     
    11601250
    11611251    // We need to check the species constructor here since checking it in the JS wrapper is too expensive for the non-optimizing tiers.
    1162     if (UNLIKELY(!speciesWatchpointsValid(exec, firstArray)))
     1252    bool isValid = speciesWatchpointsValid(exec, firstArray);
     1253    ASSERT(!scope.exception() || !isValid);
     1254    if (UNLIKELY(!isValid))
    11631255        return JSValue::encode(jsNull());
    11641256
    11651257    JSValue second = exec->uncheckedArgument(1);
    1166     if (!isJSArray(second))
     1258    if (!isJSArray(second)) {
     1259        scope.release();
    11671260        return concatAppendOne(exec, vm, firstArray, second);
     1261    }
    11681262
    11691263    JSArray* secondArray = jsCast<JSArray*>(second);
     
    11811275        RETURN_IF_EXCEPTION(scope, encodedJSValue());
    11821276
    1183         if (!moveElements(exec, vm, result, 0, firstArray, firstArraySize)
    1184             || !moveElements(exec, vm, result, firstArraySize, secondArray, secondArraySize)) {
    1185             ASSERT(scope.exception());
    1186             return JSValue::encode(JSValue());
    1187         }
     1277        bool success = moveElements(exec, vm, result, 0, firstArray, firstArraySize);
     1278        ASSERT(!scope.exception() == success);
     1279        if (UNLIKELY(!success))
     1280            return encodedJSValue();
     1281        success = moveElements(exec, vm, result, firstArraySize, secondArray, secondArraySize);
     1282        ASSERT(!scope.exception() == success);
     1283        if (UNLIKELY(!success))
     1284            return encodedJSValue();
    11881285
    11891286        return JSValue::encode(result);
     
    12511348
    12521349    VM& vm = exec->vm();
     1350    auto scope = DECLARE_THROW_SCOPE(vm);
    12531351
    12541352    if (verbose)
     
    12681366    PropertySlot constructorSlot(this, PropertySlot::InternalMethodType::VMInquiry);
    12691367    JSValue(this).get(exec, vm.propertyNames->constructor, constructorSlot);
    1270     if (constructorSlot.slotBase() != this
     1368    if (UNLIKELY(scope.exception())
     1369        || constructorSlot.slotBase() != this
    12711370        || !constructorSlot.isCacheableValue()
    12721371        || constructorSlot.getValue(exec, vm.propertyNames->constructor) != arrayConstructor)
     
    12791378    PropertySlot speciesSlot(arrayConstructor, PropertySlot::InternalMethodType::VMInquiry);
    12801379    JSValue(arrayConstructor).get(exec, vm.propertyNames->speciesSymbol, speciesSlot);
    1281     if (speciesSlot.slotBase() != arrayConstructor
     1380    if (UNLIKELY(scope.exception())
     1381        || speciesSlot.slotBase() != arrayConstructor
    12821382        || !speciesSlot.isCacheableGetter()
    12831383        || speciesSlot.getterSetter() != globalObject->speciesGetterSetter())
Note: See TracChangeset for help on using the changeset viewer.