Ignore:
Timestamp:
Sep 10, 2017, 11:23:39 PM (8 years ago)
Author:
[email protected]
Message:

Fix all ExceptionScope verification failures in JavaScriptCore.
https://bugs.webkit.org/show_bug.cgi?id=176662
<rdar://problem/34352085>

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

  1. Introduced EXCEPTION_ASSERT macros so that we can enable exception scope verification for release builds too (though this requires manually setting ENABLE_EXCEPTION_SCOPE_VERIFICATION to 1 in Platform.h).

This is useful because it allows us to run the tests more quickly to check
if any regressions have occurred. Debug builds run so much slower and not
good for a quick turn around. Debug builds are necessary though to get
trace information without inlining by the C++ compiler. This is necessary to
diagnose where the missing exception check is.

  1. Repurposed the JSC_dumpSimulatedThrows=true options to capture and dump the last simulated throw when an exception scope verification fails.

Previously, this option dumps the stack trace on all simulated throws. That
turned out to not be very useful, and slows down the debugging process.
Instead, the new implementation captures the stack trace and only dumps it
if we have a verification failure.

  1. Fixed missing exception checks and book-keeping needed to allow the JSC tests to pass with JSC_validateExceptionChecks=true.
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):

  • dfg/DFGOSRExit.cpp:

(JSC::DFG::OSRExit::executeOSRExit):

  • dfg/DFGOperations.cpp:
  • interpreter/Interpreter.cpp:

(JSC::eval):
(JSC::loadVarargs):
(JSC::Interpreter::unwind):
(JSC::Interpreter::executeProgram):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeModuleProgram):

  • jit/JITOperations.cpp:

(JSC::getByVal):

  • jsc.cpp:

(WTF::CustomGetter::customGetterAcessor):
(GlobalObject::moduleLoaderImportModule):
(GlobalObject::moduleLoaderResolve):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::getByVal):
(JSC::LLInt::setUpCall):

  • parser/Parser.h:

(JSC::Parser::popScopeInternal):

  • runtime/AbstractModuleRecord.cpp:

(JSC::AbstractModuleRecord::hostResolveImportedModule):
(JSC::AbstractModuleRecord::resolveImport):
(JSC::AbstractModuleRecord::resolveExportImpl):
(JSC::getExportedNames):
(JSC::AbstractModuleRecord::getModuleNamespace):

  • runtime/ArrayPrototype.cpp:

(JSC::getProperty):
(JSC::unshift):
(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncToLocaleString):
(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::arrayProtoPrivateFuncAppendMemcpy):

  • runtime/CatchScope.h:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/DatePrototype.cpp:

(JSC::dateProtoFuncSetTime):
(JSC::setNewValueFromTimeArgs):

  • runtime/DirectArguments.h:

(JSC::DirectArguments::length const):

  • runtime/ErrorPrototype.cpp:

(JSC::errorProtoFuncToString):

  • runtime/ExceptionFuzz.cpp:

(JSC::doExceptionFuzzing):

  • runtime/ExceptionScope.h:

(JSC::ExceptionScope::needExceptionCheck):
(JSC::ExceptionScope::assertNoException):

  • runtime/GenericArgumentsInlines.h:

(JSC::GenericArguments<Type>::defineOwnProperty):

  • runtime/HashMapImpl.h:

(JSC::HashMapImpl::rehash):

  • runtime/IntlDateTimeFormat.cpp:

(JSC::IntlDateTimeFormat::formatToParts):

  • runtime/JSArray.cpp:

(JSC::JSArray::defineOwnProperty):
(JSC::JSArray::put):

  • runtime/JSCJSValue.cpp:

(JSC::JSValue::putToPrimitive):
(JSC::JSValue::putToPrimitiveByIndex):

  • runtime/JSCJSValueInlines.h:

(JSC::JSValue::toIndex const):
(JSC::JSValue::get const):
(JSC::JSValue::getPropertySlot const):
(JSC::JSValue::equalSlowCaseInline):

  • runtime/JSGenericTypedArrayViewConstructorInlines.h:

(JSC::constructGenericTypedArrayViewFromIterator):
(JSC::constructGenericTypedArrayViewWithArguments):

  • runtime/JSGenericTypedArrayViewInlines.h:

(JSC::JSGenericTypedArrayView<Adaptor>::set):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::put):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::decode):
(JSC::globalFuncEval):
(JSC::globalFuncProtoGetter):
(JSC::globalFuncProtoSetter):
(JSC::globalFuncImportModule):

  • runtime/JSInternalPromise.cpp:

(JSC::JSInternalPromise::then):

  • runtime/JSInternalPromiseDeferred.cpp:

(JSC::JSInternalPromiseDeferred::create):

  • runtime/JSJob.cpp:

(JSC::JSJobMicrotask::run):

  • runtime/JSModuleEnvironment.cpp:

(JSC::JSModuleEnvironment::getOwnPropertySlot):
(JSC::JSModuleEnvironment::put):
(JSC::JSModuleEnvironment::deleteProperty):

  • runtime/JSModuleLoader.cpp:

(JSC::JSModuleLoader::provide):
(JSC::JSModuleLoader::loadAndEvaluateModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::linkAndEvaluateModule):
(JSC::JSModuleLoader::requestImportModule):

  • runtime/JSModuleRecord.cpp:

(JSC::JSModuleRecord::link):
(JSC::JSModuleRecord::instantiateDeclarations):

  • runtime/JSONObject.cpp:

(JSC::Stringifier::stringify):
(JSC::Stringifier::toJSON):
(JSC::JSONProtoFuncParse):

  • runtime/JSObject.cpp:

(JSC::JSObject::calculatedClassName):
(JSC::ordinarySetSlow):
(JSC::JSObject::putInlineSlow):
(JSC::JSObject::ordinaryToPrimitive const):
(JSC::JSObject::toPrimitive const):
(JSC::JSObject::hasInstance):
(JSC::JSObject::getPropertyNames):
(JSC::JSObject::toNumber const):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
(JSC::JSObject::putByIndexBeyondVectorLengthWithArrayStorage):
(JSC::JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage):
(JSC::validateAndApplyPropertyDescriptor):
(JSC::JSObject::defineOwnNonIndexProperty):
(JSC::JSObject::getGenericPropertyNames):

  • runtime/JSObject.h:

(JSC::JSObject::get const):

  • runtime/JSObjectInlines.h:

(JSC::JSObject::getPropertySlot const):
(JSC::JSObject::getPropertySlot):
(JSC::JSObject::getNonIndexPropertySlot):
(JSC::JSObject::putInlineForJSObject):

  • runtime/JSPromiseConstructor.cpp:

(JSC::constructPromise):

  • runtime/JSPromiseDeferred.cpp:

(JSC::JSPromiseDeferred::create):

  • runtime/JSScope.cpp:

(JSC::abstractAccess):
(JSC::JSScope::resolve):
(JSC::JSScope::resolveScopeForHoistingFuncDeclInEval):
(JSC::JSScope::abstractResolve):

  • runtime/LiteralParser.cpp:

(JSC::LiteralParser<CharType>::tryJSONPParse):
(JSC::LiteralParser<CharType>::parse):

  • runtime/Lookup.h:

(JSC::putEntry):

  • runtime/MapConstructor.cpp:

(JSC::constructMap):

  • runtime/NumberPrototype.cpp:

(JSC::numberProtoFuncToString):

  • runtime/ObjectConstructor.cpp:

(JSC::objectConstructorSetPrototypeOf):
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorGetOwnPropertyDescriptors):
(JSC::objectConstructorAssign):
(JSC::objectConstructorValues):
(JSC::toPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
(JSC::defineProperties):
(JSC::objectConstructorDefineProperties):
(JSC::ownPropertyKeys):

  • runtime/ObjectPrototype.cpp:

(JSC::objectProtoFuncHasOwnProperty):
(JSC::objectProtoFuncIsPrototypeOf):
(JSC::objectProtoFuncLookupGetter):
(JSC::objectProtoFuncLookupSetter):
(JSC::objectProtoFuncToLocaleString):
(JSC::objectProtoFuncToString):

  • runtime/Options.h:
  • runtime/ParseInt.h:

(JSC::toStringView):

  • runtime/ProxyObject.cpp:

(JSC::performProxyGet):
(JSC::ProxyObject::performPut):

  • runtime/ReflectObject.cpp:

(JSC::reflectObjectDefineProperty):

  • runtime/RegExpConstructor.cpp:

(JSC::toFlags):
(JSC::regExpCreate):
(JSC::constructRegExp):

  • runtime/RegExpObject.cpp:

(JSC::collectMatches):

  • runtime/RegExpObjectInlines.h:

(JSC::RegExpObject::execInline):
(JSC::RegExpObject::matchInline):

  • runtime/RegExpPrototype.cpp:

(JSC::regExpProtoFuncTestFast):
(JSC::regExpProtoFuncExec):
(JSC::regExpProtoFuncMatchFast):
(JSC::regExpProtoFuncToString):
(JSC::regExpProtoFuncSplitFast):

  • runtime/ScriptExecutable.cpp:

(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::prepareForExecutionImpl):

  • runtime/SetConstructor.cpp:

(JSC::constructSet):

  • runtime/ThrowScope.cpp:

(JSC::ThrowScope::simulateThrow):

  • runtime/VM.cpp:

(JSC::VM::verifyExceptionCheckNeedIsSatisfied):

  • runtime/VM.h:
  • runtime/WeakMapPrototype.cpp:

(JSC::protoFuncWeakMapSet):

  • runtime/WeakSetPrototype.cpp:

(JSC::protoFuncWeakSetAdd):

  • wasm/js/WebAssemblyModuleConstructor.cpp:

(JSC::WebAssemblyModuleConstructor::createModule):

  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::link):

  • wasm/js/WebAssemblyPrototype.cpp:

(JSC::reject):
(JSC::webAssemblyCompileFunc):
(JSC::resolve):
(JSC::webAssemblyInstantiateFunc):

Source/WebCore:

No new tests because this is covered by existing tests with the JSC_validateExceptionChecks=true enabled.

  • bindings/js/JSCustomElementInterface.cpp:

(WebCore::JSCustomElementInterface::tryToConstructCustomElement):

  • bindings/js/JSCustomElementRegistryCustom.cpp:

(WebCore::whenDefinedPromise):

  • bindings/js/JSDOMConvertRecord.h:
  • bindings/js/JSDOMMapLike.cpp:

(WebCore::createBackingMap):

  • bindings/js/JSDOMPromiseDeferred.cpp:

(WebCore::DeferredPromise::callFunction):
(WebCore::DeferredPromise::reject):

  • bindings/js/JSDOMPromiseDeferred.h:

(WebCore::callPromiseFunction):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r221822 r221849  
    536536    PropertyName constructor(vm.propertyNames->constructor);
    537537    if (object->getPropertySlot(exec, constructor, slot)) {
     538        EXCEPTION_ASSERT(!scope.exception());
    538539        if (slot.isValue()) {
    539540            JSValue constructorValue = slot.getValue(exec, constructor);
     
    550551        }
    551552    }
    552     ASSERT(!scope.exception() || prototypeFunctionName.isNull());
     553    EXCEPTION_ASSERT(!scope.exception() || prototypeFunctionName.isNull());
    553554    if (UNLIKELY(scope.exception()))
    554555        scope.clearException();
     
    659660            ProxyObject* proxy = jsCast<ProxyObject*>(current);
    660661            PutPropertySlot slot(receiver, shouldThrow);
     662            scope.release();
    661663            return proxy->ProxyObject::put(proxy, exec, propertyName, value, slot);
    662664        }
     
    717719
    718720            // 9.1.9.1-4-d-iv Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
     721            scope.release();
    719722            return receiverObject->methodTable(vm)->defineOwnProperty(receiverObject, exec, propertyName, valueDescriptor, shouldThrow);
    720723        }
     
    722725        // 9.1.9.1-4-e Else Receiver does not currently have a property P,
    723726        // 9.1.9.1-4-e-i Return ? CreateDataProperty(Receiver, P, V).
     727        scope.release();
    724728        return receiverObject->methodTable(vm)->defineOwnProperty(receiverObject, exec, propertyName, PropertyDescriptor(value, None), shouldThrow);
    725729    }
     
    741745    CallData callData;
    742746    CallType callType = setterObject->methodTable(vm)->getCallData(setterObject, callData);
     747    scope.release();
    743748    call(exec, setterObject, callType, callData, receiver, args);
    744749
     
    773778            if (gs.isGetterSetter()) {
    774779                bool result = callSetter(exec, slot.thisValue(), gs, value, slot.isStrictMode() ? StrictMode : NotStrictMode);
     780                RETURN_IF_EXCEPTION(scope, false);
    775781                if (!structure()->isDictionary())
    776782                    slot.setCacheableSetter(obj, offset);
     
    793799        if (!obj->staticPropertiesReified()) {
    794800            if (obj->classInfo(vm)->hasStaticSetterOrReadonlyProperties()) {
    795                 if (auto entry = obj->findPropertyHashEntry(vm, propertyName))
     801                if (auto entry = obj->findPropertyHashEntry(vm, propertyName)) {
     802                    scope.release();
    796803                    return putEntry(exec, entry->table->classForThis, entry->value, obj, this, propertyName, value, slot);
     804                }
    797805            }
    798806        }
     
    802810            // https://bugs.webkit.org/show_bug.cgi?id=155012
    803811            ProxyObject* proxy = jsCast<ProxyObject*>(obj);
     812            scope.release();
    804813            return proxy->ProxyObject::put(proxy, exec, propertyName, value, slot);
    805814        }
     
    19481957    if (hint == PreferString) {
    19491958        value = callToPrimitiveFunction(exec, this, vm.propertyNames->toString, hint);
    1950         ASSERT(!scope.exception() || scope.exception() == value.asCell());
     1959        EXCEPTION_ASSERT(!scope.exception() || scope.exception() == value.asCell());
    19511960        if (value)
    19521961            return value;
    19531962        value = callToPrimitiveFunction(exec, this, vm.propertyNames->valueOf, hint);
    1954         ASSERT(!scope.exception() || scope.exception() == value.asCell());
     1963        EXCEPTION_ASSERT(!scope.exception() || scope.exception() == value.asCell());
    19551964        if (value)
    19561965            return value;
    19571966    } else {
    19581967        value = callToPrimitiveFunction(exec, this, vm.propertyNames->valueOf, hint);
    1959         ASSERT(!scope.exception() || scope.exception() == value.asCell());
     1968        EXCEPTION_ASSERT(!scope.exception() || scope.exception() == value.asCell());
    19601969        if (value)
    19611970            return value;
    19621971        value = callToPrimitiveFunction(exec, this, vm.propertyNames->toString, hint);
    1963         ASSERT(!scope.exception() || scope.exception() == value.asCell());
     1972        EXCEPTION_ASSERT(!scope.exception() || scope.exception() == value.asCell());
    19641973        if (value)
    19651974            return value;
     
    19861995        return value;
    19871996
     1997    scope.release();
    19881998    return this->methodTable(vm)->defaultValue(this, exec, preferredType);
    19891999}
     
    20472057        JSValue prototype = get(exec, vm.propertyNames->prototype);
    20482058        RETURN_IF_EXCEPTION(scope, false);
     2059        scope.release();
    20492060        return defaultHasInstance(exec, value, prototype);
    20502061    }
    2051     if (info.implementsHasInstance())
     2062    if (info.implementsHasInstance()) {
     2063        scope.release();
    20522064        return methodTable(vm)->customHasInstance(this, exec, value);
     2065    }
    20532066    throwException(exec, scope, createInvalidInstanceofParameterErrorNotFunction(exec, this));
    20542067    return false;
     
    20622075    RETURN_IF_EXCEPTION(scope, false);
    20632076
     2077    scope.release();
    20642078    return hasInstance(exec, value, hasInstanceValue);
    20652079}
     
    21142128    while(1) {
    21152129        if (prototype->structure(vm)->typeInfo().overridesGetPropertyNames()) {
     2130            scope.release();
    21162131            prototype->methodTable(vm)->getPropertyNames(prototype, exec, propertyNames, mode);
    2117             break;
     2132            return;
    21182133        }
    21192134        prototype->methodTable(vm)->getOwnPropertyNames(prototype, exec, propertyNames, mode);
     
    22222237    JSValue primitive = toPrimitive(exec, PreferNumber);
    22232238    RETURN_IF_EXCEPTION(scope, 0.0); // should be picked up soon in Nodes.cpp
     2239    scope.release();
    22242240    return primitive.toNumber(exec);
    22252241}
     
    23892405        if (!descriptor.attributes() && descriptor.value() && canDoFastPutDirectIndex(this)) {
    23902406            ASSERT(!descriptor.isAccessorDescriptor());
     2407            scope.release();
    23912408            return putDirectIndex(exec, index, descriptor.value(), 0, throwException ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
    23922409        }
     
    24402457    PropertyDescriptor current;
    24412458    entryInMap->get(current);
    2442     if (descriptor.isEmpty() || descriptor.equalTo(exec, current))
     2459    bool isEmptyOrEqual = descriptor.isEmpty() || descriptor.equalTo(exec, current);
     2460    RETURN_IF_EXCEPTION(scope, false);
     2461    if (isEmptyOrEqual)
    24432462        return true;
    24442463
     
    25752594        SparseArrayValueMap* map = allocateSparseIndexMap(vm);
    25762595        bool result = map->putEntry(exec, this, i, value, false);
     2596        RETURN_IF_EXCEPTION(scope, false);
    25772597        ASSERT(i >= arrayStorage()->length());
    25782598        arrayStorage()->setLength(i + 1);
     
    26482668        // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
    26492669        map = allocateSparseIndexMap(vm);
     2670        scope.release();
    26502671        return map->putEntry(exec, this, i, value, shouldThrow);
    26512672    }
     
    26642685    // We will continue  to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
    26652686    unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
    2666     if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length))
     2687    if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length)) {
     2688        scope.release();
    26672689        return map->putEntry(exec, this, i, value, shouldThrow);
     2690    }
    26682691
    26692692    // Reread m_storage after increaseVectorLength, update m_numValuesInVector.
     
    27842807        // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
    27852808        map = allocateSparseIndexMap(vm);
     2809        scope.release();
    27862810        return map->putDirect(exec, this, i, value, attributes, mode);
    27872811    }
     
    28042828    // We will continue  to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
    28052829    unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
    2806     if (map->sparseMode() || attributes || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length))
     2830    if (map->sparseMode() || attributes || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length)) {
     2831        scope.release();
    28072832        return map->putDirect(exec, this, i, value, attributes, mode);
     2833    }
    28082834
    28092835    // Reread m_storage after increaseVectorLength, update m_numValuesInVector.
     
    33523378        return true;
    33533379    // Step 4.
    3354     if (current.equalTo(exec, descriptor))
     3380    bool isEqual = current.equalTo(exec, descriptor);
     3381    RETURN_IF_EXCEPTION(scope, false);
     3382    if (isEqual)
    33553383        return true;
    33563384
     
    33693397        if (!current.attributesEqual(descriptor) && object) {
    33703398            object->methodTable(vm)->deleteProperty(object, exec, propertyName);
     3399            RETURN_IF_EXCEPTION(scope, false);
    33713400            return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
    33723401        }
     
    33843413
    33853414        object->methodTable(vm)->deleteProperty(object, exec, propertyName);
     3415        RETURN_IF_EXCEPTION(scope, false);
    33863416        return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
    33873417    }
     
    34033433            return true;
    34043434        object->methodTable(vm)->deleteProperty(object, exec, propertyName);
     3435        RETURN_IF_EXCEPTION(scope, false);
    34053436        return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
    34063437    }
     
    34483479        return true;
    34493480    object->methodTable(vm)->deleteProperty(object, exec, propertyName);
     3481    RETURN_IF_EXCEPTION(scope, false);
    34503482    unsigned attrs = descriptor.attributesOverridingCurrent(current);
    34513483    object->putDirectAccessor(exec, propertyName, getterSetter, attrs | Accessor);
     
    34673499    bool isExtensible = this->isExtensible(exec);
    34683500    RETURN_IF_EXCEPTION(throwScope, false);
     3501    throwScope.release();
    34693502    return validateAndApplyPropertyDescriptor(exec, this, propertyName, isExtensible, descriptor, isCurrentDefined, current, throwException);
    34703503}
     
    35953628    while (true) {
    35963629        if (prototype->structure(vm)->typeInfo().overridesGetPropertyNames()) {
     3630            scope.release();
    35973631            prototype->methodTable(vm)->getPropertyNames(prototype, exec, propertyNames, mode);
    3598             break;
     3632            return;
    35993633        }
    36003634        prototype->methodTable(vm)->getOwnPropertyNames(prototype, exec, propertyNames, mode);
Note: See TracChangeset for help on using the changeset viewer.