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/jit/JITOperations.cpp

    r221832 r221849  
    354354    Identifier ident = Identifier::fromUid(vm, key);
    355355    LOG_IC((ICEvent::OperationIn, base->classInfo(*vm), ident));
     356    scope.release();
    356357    return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
    357358}
     
    554555        if (baseValue.isObject()) {
    555556            JSObject* object = asObject(baseValue);
    556             if (object->canSetIndexQuickly(i))
     557            if (object->canSetIndexQuickly(i)) {
    557558                object->setIndexQuickly(vm, i, value);
    558             else {
    559                 // FIXME: This will make us think that in-bounds typed array accesses are actually
    560                 // out-of-bounds.
    561                 // https://bugs.webkit.org/show_bug.cgi?id=149886
    562                 byValInfo->arrayProfile->setOutOfBounds();
    563                 object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
     559                return;
    564560            }
    565         } else
    566             baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
     561
     562            // FIXME: This will make us think that in-bounds typed array accesses are actually
     563            // out-of-bounds.
     564            // https://bugs.webkit.org/show_bug.cgi?id=149886
     565            byValInfo->arrayProfile->setOutOfBounds();
     566            scope.release();
     567            object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
     568            return;
     569        }
     570
     571        scope.release();
     572        baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
    567573        return;
    568574    }
     
    604610        }
    605611
     612        scope.release();
    606613        baseObject->putDirectIndex(callFrame, index, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
    607614        return;
     
    613620        if (subscriptAsDouble == subscriptAsUInt32 && isIndex(subscriptAsUInt32)) {
    614621            byValInfo->tookSlowPath = true;
     622            scope.release();
    615623            baseObject->putDirectIndex(callFrame, subscriptAsUInt32, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
    616624            return;
     
    624632    if (std::optional<uint32_t> index = parseIndex(property)) {
    625633        byValInfo->tookSlowPath = true;
     634        scope.release();
    626635        baseObject->putDirectIndex(callFrame, index.value(), value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
    627636        return;
     
    958967        CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
    959968        JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, callee, scope, kind, *codeBlockSlot);
    960         ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
     969        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
    961970        if (error) {
    962971            return encodeResult(
     
    10171026       
    10181027        JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, callee, scope, kind, codeBlock);
    1019         ASSERT_UNUSED(throwScope, throwScope.exception() == reinterpret_cast<Exception*>(error));
     1028        EXCEPTION_ASSERT_UNUSED(throwScope, throwScope.exception() == reinterpret_cast<Exception*>(error));
    10201029        if (error)
    10211030            return;
     
    10441053    JSValue calleeAsValue = execCallee->guaranteedJSValueCallee();
    10451054    calleeAsFunctionCell = getJSFunction(calleeAsValue);
    1046     if (UNLIKELY(!calleeAsFunctionCell))
     1055    if (UNLIKELY(!calleeAsFunctionCell)) {
     1056        throwScope.release();
    10471057        return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
     1058    }
    10481059   
    10491060    JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
     
    10621073        CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
    10631074        JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, function, scope, kind, *codeBlockSlot);
    1064         ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
     1075        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
    10651076        if (error) {
    10661077            return encodeResult(
     
    15941605    RETURN_IF_EXCEPTION(scope, void());
    15951606
     1607    scope.release();
    15961608    if (accessorType == AccessorType::Getter)
    15971609        base->putGetter(exec, propertyKey, accessor, attribute);
     
    17611773            if (asString(baseValue)->canGetIndex(i)) {
    17621774                ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(operationGetByValString));
     1775                scope.release();
    17631776                return asString(baseValue)->getIndex(exec, i);
    17641777            }
     
    17771790        }
    17781791
     1792        scope.release();
    17791793        return baseValue.get(exec, i);
    17801794    }
     
    17891803        byValInfo->tookSlowPath = true;
    17901804
     1805    scope.release();
    17911806    return baseValue.get(exec, property);
    17921807}
     
    19801995    if (LIKELY(subscript.isUInt32())) {
    19811996        uint32_t i = subscript.asUInt32();
    1982         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
    1983             result = asString(baseValue)->getIndex(exec, i);
    1984         else {
    1985             result = baseValue.get(exec, i);
    1986             if (!isJSString(baseValue)) {
    1987                 ASSERT(exec->bytecodeOffset());
    1988                 ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo->stubRoutine ? operationGetByValGeneric : operationGetByValOptimize));
    1989             }
     1997        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
     1998            scope.release();
     1999            return JSValue::encode(asString(baseValue)->getIndex(exec, i));
     2000        }
     2001        result = baseValue.get(exec, i);
     2002        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2003        if (!isJSString(baseValue)) {
     2004            ASSERT(exec->bytecodeOffset());
     2005            ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo->stubRoutine ? operationGetByValGeneric : operationGetByValOptimize));
    19902006        }
    19912007    } else {
     
    19942010        auto property = subscript.toPropertyKey(exec);
    19952011        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2012        scope.release();
    19962013        result = baseValue.get(exec, property);
    19972014    }
     
    20122029
    20132030    JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
     2031    RETURN_IF_EXCEPTION(scope, false);
    20142032    if (!baseObj)
    20152033        return false;
    20162034    bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, Identifier::fromUid(&vm, uid));
     2035    RETURN_IF_EXCEPTION(scope, false);
    20172036    if (!couldDelete && exec->codeBlock()->isStrictMode())
    20182037        throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     
    20322051
    20332052    JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
     2053    RETURN_IF_EXCEPTION(scope, false);
    20342054    JSValue key = JSValue::decode(encodedKey);
    20352055    if (!baseObj)
     
    20412061        couldDelete = baseObj->methodTable(vm)->deletePropertyByIndex(baseObj, exec, index);
    20422062    else {
    2043         RETURN_IF_EXCEPTION(scope, false);
    20442063        Identifier property = key.toPropertyKey(exec);
    20452064        RETURN_IF_EXCEPTION(scope, false);
    20462065        couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, property);
    20472066    }
     2067    RETURN_IF_EXCEPTION(scope, false);
    20482068    if (!couldDelete && exec->codeBlock()->isStrictMode())
    20492069        throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     
    21982218    ASSERT(getPutInfo.resolveType() != ModuleVar);
    21992219
     2220    throwScope.release();
    22002221    return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
    22012222        if (!found) {
     
    22492270
    22502271    bool hasProperty = scope->hasProperty(exec, ident);
     2272    EXCEPTION_ASSERT(!throwScope.exception() || !hasProperty);
    22512273    if (hasProperty
    22522274        && scope->isGlobalLexicalEnvironment()
     
    25212543    double a = op1.toNumber(exec);
    25222544    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2545    scope.release();
    25232546    double b = op2.toNumber(exec);
    25242547    return JSValue::encode(jsNumber(a * b));
     
    26222645    JSValue operand = JSValue::decode(encodedOperand);
    26232646    double number = operand.toNumber(exec);
    2624     if (UNLIKELY(scope.exception()))
    2625         return JSValue::encode(JSValue());
     2647    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    26262648    return JSValue::encode(jsNumber(-number));
    26272649}
     
    26362658    arithProfile.observeLHS(operand);
    26372659    double number = operand.toNumber(exec);
    2638     if (UNLIKELY(scope.exception()))
    2639         return JSValue::encode(JSValue());
     2660    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    26402661
    26412662    JSValue result = jsNumber(-number);
     
    26732694   
    26742695    double number = operand.toNumber(exec);
    2675     if (UNLIKELY(scope.exception()))
    2676         return JSValue::encode(JSValue());
     2696    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    26772697    JSValue result = jsNumber(-number);
    26782698    arithProfile->observeResult(result);
     
    26972717
    26982718    double number = operand.toNumber(exec);
    2699     if (UNLIKELY(scope.exception()))
    2700         return JSValue::encode(JSValue());
     2719    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    27012720    return JSValue::encode(jsNumber(-number));
    27022721}
     
    27102729    double a = op1.toNumber(exec);
    27112730    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     2731    scope.release();
    27122732    double b = op2.toNumber(exec);
    27132733    return JSValue::encode(jsNumber(a - b));
Note: See TracChangeset for help on using the changeset viewer.