Add CatchScope and force all exception checks to be via ThrowScope or CatchScope.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Sep 2016 22:10:50 +0000 (22:10 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Sep 2016 22:10:50 +0000 (22:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161498

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This patch refactors the ThrowScope class, and introduces a base ExceptionScope
that ThrowScope extends.  A CatchScope which extends the ExceptionScope is also
introduced.

ENABLE(THROW_SCOPE_VERIFICATION) is now renamed to ENABLE(EXCEPTION_SCOPE_VERIFICATION)
which is a more suitable name now.

Note: exception scope verification is still disabled by default.  There are still
many places that need to be fixed up or re-expressed in a way that is friendly
to the verification.  I'll address those in subsequent patches.

After this patch, the code will statically enforce that:
1. all calls to throwException() go through a ThrowScope.
2. all calls to clearException() go through a CatchScope.
3. all exception checks go through an ExceptionScope in the form of a ThrowScope
   or CatchScope.

A Summary of how to use ExceptionScopes
=======================================
1. If a function can throw a JS exception, it should declare a ThrowScope at the
   top of the function (as early as possible).

2. If a function can clear JS exceptions, it should declare a CatchScope at the
   top of the function (as early as possible).

Declaring a ThrowScope in a function means that the function may throw an exception
that its caller will have to handle.  Declaring a CatchScope in a function means
that the function intends to clear pending exceptions before returning to its
caller.

For more details, see the notes below.

Everything you may want to know about ExceptionScopes
=====================================================
ExceptionScope verification works to simulate exception throws and detect cases
where exception checks are missing.  The notes below will cover:

    1. The VM::m_needExceptionCheck bit
    2. ThrowScopes and CatchScopes
    3. Verification of needed exception checks
    3. Checking Exceptions
    4. Simulating throws
    5. Using ThrowScope::release()
    6. Checking exceptions with ThrowScope::exception() / CatchScope::exception()
    7. Checking exceptions by checking callee results
    8. Debugging verification errors

1. The VM::m_needExceptionCheck bit

   The VM has a m_needExceptionCheck bit that indicates when an exception may be
   thrown.  You can think of the m_needExceptionCheck bit being set as a simulated
   throw.

2. ThrowScopes and CatchScopes

   Only ThrowScopes may throwException.  Only CatchScopes may catchException.

   Every throw site must declare a ThrowScope instance using DECLARE_THROW_SCOPE
   at the top of its function (as early as possible) e.g.

        void foo(...)
        {
            auto scope = DECLARE_THROW_SCOPE(vm);
            ...
            throwException(exec, scope, ...);
        }

   Note: by convention, every throw helper function must take a ThrowScope argument
   instead of instantiating its own ThrowScope.  This allows the throw to be
   attributed to the client code rather than the throw helper itself.

   Every catch site (i.e. a site that calls clearException()) must declare a
   CatchScope instance using DECLARE_CATCH_SCOPE at the top of its function.

   If a function can both throw or clear exceptions, then the ThrowScope should
   be declared first so that it can simulate a throw to the function's caller.

   Note: ThrowScope and CatchScope both extend ExceptionScope so that ThrowScopes
   can be aware if there's an enclosing CatchScope between it and the point where
   C++ code returns to JS code.  This is needed to determine if the ThrowScope
   should simulate a re-throw or not.  See (4) below for more details on returning
   to JS code.

3. Verification of needed exception checks

   a. On construction, each ThrowScope and CatchScope will verify that
      VM::m_needExceptionCheck is not set.

      This ensures that the caller of the current function has checked for exceptions
      where needed before doing more work which lead to calling the current function.

   b. On destruction, each ThrowScope and CatchScope will verify that
      VM::m_needExceptionCheck is not set. This verification will be skipped if
      the ThrowScope has been released (see (5) below).

      This ensures that the function that owns this exception scope is not missing
      any exception checks before returning.

   c. When throwing an exception, the ThrowScope will verify that VM::m_needExceptionCheck
      is not already set, unless it's been ask to rethrow the same Exception object.

4. Simulating throws

   Throws are simulated by setting the m_needExceptionCheck bit.

   The bit will only be set in the ThrowScope destructor except when the ThrowScope
   detects the caller is a LLInt or JIT function.  LLInt or JIT functions will always
   check for exceptions after a host C++ function returns to it.  However, they will
   not clear the m_needExceptionCheck bit.

   Hence, if the ThrowScope destructor detects the caller is a LLInt or JIT function,
   it will just skip the setting of the bit.

   Note: it is not needed nor correct to set the m_needExceptionCheck bit in the
   throwException methods.  This is because, in practice, we always return
   immediately after throwing an exception.  It doesn't make sense to set the bit in
   the throw just to have to clear it immediately after before we do verification in
   the ThrowScope destructor.

5. Using ThrowScope::release()

   Calling release() means that the scope is released from its obligation to
   verify the VM::m_needExceptionCheck bit on destruction.

   release() should only be used at the bottom of a function if:

   a. This function is going to let its caller check and handle the exception, e.g.

        void foo(...)
        {
            auto scope = DECLARE_THROW_SCOPE(vm);
            auto result = goo(); // may throw.

            ... // Code that will are not affected by a pending exceptions.

            scope.release(); // tell the ThrowScope that the caller will handle the exception.
            return result;
        }

   b. This function is going to do a tail call that may throw.

        void foo(...)
        {
            auto scope = DECLARE_THROW_SCOPE(vm);
            ...
            scope.release(); // tell the ThrowScope that the caller will handle the exception.
            return goo(); // may throw.
        }

      release() should not be used in code paths that branch. For example:

        void foo(...)
        {
            auto scope = DECLARE_THROW_SCOPE(vm);

            auto result = goo1(); // may throw.
            scope.release(); // WRONG !!! Don't do this.
            if (result)
                return;

            result = goo2(); // may throw.
            ...
            return result;
        }

    The above will result in a verification error in goo2()'s ThrowScope.  The
    proper way to fix this verification is to do either (6) or (7) below.

 6. Checking exceptions with ThrowScope::exception() / CatchScope::exception()

    ThrowScope/CatchScope::exception() returns the thrown Exception object if
    there is one pending.  Else, it returns nullptr.

    It also clears the m_needExceptionCheck bit thereby indicating that we've
    satisfied the needed exception check.  For example,

        void foo(...)
        {
            auto scope = DECLARE_THROW_SCOPE(vm);

            auto result = goo1(); // may throw.
            if (scope.exception())
                return;

            result = goo2(); // may throw.
            ...
            return result;
        }

    But sometimes, for optimization reasons, we may choose to test the result of
    the callee function instead doing a load of the VM exception value.  See (7)
    below.

 7. Checking exceptions by checking callee results

    This approach should only be applied when it makes a difference to performance.
    If we need to do this, we should add an ASSERT() that invokes the scope's
    exception() method to verify the result.  Since exception scope verification
    is only done on DEBUG builds, this ASSERT will satisfy the verification
    requirements without impacting performance.  For example,

        void foo(...)
        {
            auto scope = DECLARE_THROW_SCOPE(vm);

            bool failed = goo1(); // may throw.
            ASSERT(!!scope.exception() == failed)
            if (failed)
                return;

            result = goo2(); // may throw.
            ...
            return result;
        }

 8. Debugging verification errors

    a. When verification fails, you will see a message followed by an assertion
       failure.  For example:

    ERROR: Unchecked JS exception:
        This scope can throw a JS exception: setUpCall @ /Volumes/Data/ws6/OpenSource/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:1245
            (ExceptionScope::m_recursionDepth was ...)
        But the exception was unchecked as of this scope: varargsSetup @ /Volumes/Data/ws6/OpenSource/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:1398
            (ExceptionScope::m_recursionDepth was ...)
        [ backtrace here ]

       The message tells you that failure was detected at in varargsSetup() at
       LLIntSlowPaths.cpp line 1398, and that the missing exception check should
       have happened somewhere between the call to setUpCall() at LLIntSlowPaths.cpp
       line 1245 and it.

       If that is insufficient information, you can ...

    b. Dump simulated throws

       Re-run the test case with JSC_dumpSimulatedThrows=true.  You will also see
       back traces at each simulated throw.

    c. Narrowing down the source of a simulated throw

       Another technique for narrowing down the source of simulated throws is by
       further dividing a function to smaller regions by separating each region
       with additional local throw scopes.  For example,

        ... // Region 1
        { auto scope = DECLARE_THROW_SCOPE(vm); }
        ... // Region 2
        { auto scope = DECLARE_THROW_SCOPE(vm); }
        ... // Region 3

* API/APIUtils.h:
(handleExceptionIfNeeded):
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bindings/ScriptFunctionCall.cpp:
(Deprecated::ScriptFunctionCall::call):
* bindings/ScriptValue.cpp:
(Deprecated::ScriptValue::toString):
* debugger/Debugger.cpp:
(JSC::Debugger::pauseIfNeeded):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::evaluateWithScopeExtension):
* dfg/DFGOSRExitCompiler.cpp:
* dfg/DFGOperations.cpp:
(JSC::DFG::operationPutByValInternal):
* inspector/InjectedScriptManager.cpp:
(Inspector::InjectedScriptManager::createInjectedScript):
* inspector/JSGlobalObjectInspectorController.cpp:
(Inspector::JSGlobalObjectInspectorController::reportAPIException):
* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::evaluateWithScopeExtension):
(Inspector::JSInjectedScriptHost::getInternalProperties):
(Inspector::JSInjectedScriptHost::weakMapEntries):
(Inspector::JSInjectedScriptHost::weakSetEntries):
(Inspector::JSInjectedScriptHost::iteratorEntries):
* inspector/JSJavaScriptCallFrame.cpp:
(Inspector::JSJavaScriptCallFrame::evaluateWithScopeExtension):
* inspector/ScriptCallStackFactory.cpp:
(Inspector::extractSourceInformationFromException):
* interpreter/CachedCall.h:
(JSC::CachedCall::CachedCall):
* interpreter/CallFrame.h:
(JSC::ExecState::clearException): Deleted.
(JSC::ExecState::exception): Deleted.
(JSC::ExecState::hadException): Deleted.
(JSC::ExecState::lastException): Deleted.
(JSC::ExecState::clearLastException): Deleted.
* interpreter/Interpreter.cpp:
(JSC::eval):
(JSC::sizeOfVarargs):
(JSC::notifyDebuggerOfUnwinding):
(JSC::Interpreter::unwind):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
(JSC::Interpreter::debug):
* interpreter/Interpreter.h:
(JSC::SuspendExceptionScope::SuspendExceptionScope):
* interpreter/ShadowChicken.cpp:
(JSC::ShadowChicken::functionsOnStack):
* jit/JITCode.cpp:
(JSC::JITCode::execute):
* jit/JITExceptions.cpp:
(JSC::genericUnwind):
* jit/JITOperations.cpp:
(JSC::getByVal):
* jsc.cpp:
(WTF::ImpureGetter::getOwnPropertySlot):
(GlobalObject::moduleLoaderResolve):
(GlobalObject::moduleLoaderFetch):
(functionCreateElement):
(functionRun):
(functionRunString):
(functionLoad):
(functionLoadString):
(functionReadFile):
(functionCheckSyntax):
(functionSetRandomSeed):
(functionLoadModule):
(functionCreateBuiltin):
(functionCheckModuleSyntax):
(functionGenerateHeapSnapshot):
(functionSamplingProfilerStackTraces):
(dumpException):
(checkUncaughtException):
(runWithScripts):
(runInteractive):
* llint/LLIntExceptions.cpp:
(JSC::LLInt::returnToThrow):
(JSC::LLInt::callToThrow):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* profiler/ProfilerBytecodeSequence.cpp:
(JSC::Profiler::BytecodeSequence::addSequenceProperties):
* profiler/ProfilerCompilation.cpp:
(JSC::Profiler::Compilation::toJS):
* profiler/ProfilerDatabase.cpp:
(JSC::Profiler::Database::toJS):
* profiler/ProfilerOSRExitSite.cpp:
(JSC::Profiler::OSRExitSite::toJS):
* profiler/ProfilerOriginStack.cpp:
(JSC::Profiler::OriginStack::toJS):
* runtime/ArrayPrototype.cpp:
(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::moveElements):
(JSC::concatAppendOne):
(JSC::arrayProtoPrivateFuncConcatMemcpy):
* runtime/BooleanConstructor.cpp:
(JSC::constructWithBooleanConstructor):
* runtime/CallData.cpp:
(JSC::call):
* runtime/CatchScope.cpp: Added.
(JSC::CatchScope::CatchScope):
(JSC::CatchScope::~CatchScope):
* runtime/CatchScope.h: Added.
(JSC::CatchScope::clearException):
(JSC::CatchScope::CatchScope):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::opIn):
* runtime/CommonSlowPathsExceptions.cpp:
(JSC::CommonSlowPaths::interpreterThrowInCaller):
* runtime/Completion.cpp:
(JSC::evaluate):
(JSC::rejectPromise):
(JSC::loadAndEvaluateModule):
(JSC::loadModule):
* runtime/ConsoleObject.cpp:
(JSC::consoleProtoFuncAssert):
(JSC::consoleProtoFuncProfile):
(JSC::consoleProtoFuncProfileEnd):
(JSC::consoleProtoFuncTakeHeapSnapshot):
(JSC::consoleProtoFuncTime):
(JSC::consoleProtoFuncTimeEnd):
* runtime/DateConstructor.cpp:
(JSC::constructDate):
(JSC::dateParse):
* runtime/DatePrototype.cpp:
(JSC::dateProtoFuncToPrimitiveSymbol):
(JSC::dateProtoFuncToJSON):
* runtime/ErrorConstructor.cpp:
(JSC::Interpreter::constructWithErrorConstructor):
* runtime/ErrorInstance.cpp:
(JSC::ErrorInstance::sanitizedToString):
* runtime/ErrorPrototype.cpp:
(JSC::errorProtoFuncToString):
* runtime/ExceptionEventLocation.cpp: Added.
(WTF::printInternal):
* runtime/ExceptionEventLocation.h: Copied from Source/JavaScriptCore/runtime/ThrowScopeLocation.h.
(JSC::ExceptionEventLocation::ExceptionEventLocation):
(JSC::ThrowScopeLocation::ThrowScopeLocation): Deleted.
* runtime/ExceptionHelpers.h:
* runtime/ExceptionScope.cpp: Added.
(JSC::ExceptionScope::ExceptionScope):
(JSC::ExceptionScope::~ExceptionScope):
* runtime/ExceptionScope.h: Added.
(JSC::ExceptionScope::vm):
(JSC::ExceptionScope::recursionDepth):
(JSC::ExceptionScope::exception):
(JSC::ExceptionScope::ExceptionScope):
* runtime/FunctionConstructor.cpp:
(JSC::constructFunctionSkippingEvalEnabledCheck):
* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncBind):
* runtime/GenericArgumentsInlines.h:
(JSC::GenericArguments<Type>::copyToArguments):
* runtime/GetterSetter.cpp:
(JSC::callGetter):
* runtime/InspectorInstrumentationObject.cpp:
(JSC::inspectorInstrumentationObjectLog):
* runtime/InternalFunction.cpp:
(JSC::InternalFunction::createSubclassStructure):
* runtime/IntlCollator.cpp:
(JSC::IntlCollator::initializeCollator):
(JSC::IntlCollator::createCollator):
(JSC::IntlCollator::resolvedOptions):
* runtime/IntlCollatorConstructor.cpp:
(JSC::constructIntlCollator):
(JSC::IntlCollatorConstructorFuncSupportedLocalesOf):
* runtime/IntlCollatorPrototype.cpp:
(JSC::IntlCollatorFuncCompare):
(JSC::IntlCollatorPrototypeGetterCompare):
* runtime/IntlDateTimeFormat.cpp:
(JSC::toDateTimeOptionsAnyDate):
(JSC::IntlDateTimeFormat::initializeDateTimeFormat):
(JSC::IntlDateTimeFormat::resolvedOptions):
(JSC::IntlDateTimeFormat::format):
* runtime/IntlDateTimeFormatConstructor.cpp:
(JSC::constructIntlDateTimeFormat):
(JSC::IntlDateTimeFormatConstructorFuncSupportedLocalesOf):
* runtime/IntlDateTimeFormatPrototype.cpp:
(JSC::IntlDateTimeFormatFuncFormatDateTime):
(JSC::IntlDateTimeFormatPrototypeGetterFormat):
* runtime/IntlNumberFormat.cpp:
(JSC::IntlNumberFormat::initializeNumberFormat):
(JSC::IntlNumberFormat::createNumberFormat):
(JSC::IntlNumberFormat::resolvedOptions):
* runtime/IntlNumberFormatConstructor.cpp:
(JSC::constructIntlNumberFormat):
(JSC::IntlNumberFormatConstructorFuncSupportedLocalesOf):
* runtime/IntlNumberFormatPrototype.cpp:
(JSC::IntlNumberFormatFuncFormatNumber):
(JSC::IntlNumberFormatPrototypeGetterFormat):
* runtime/IntlObject.cpp:
(JSC::intlBooleanOption):
(JSC::intlStringOption):
(JSC::intlNumberOption):
(JSC::canonicalizeLocaleList):
(JSC::supportedLocales):
* runtime/IntlObjectInlines.h:
(JSC::constructIntlInstanceWithWorkaroundForLegacyIntlConstructor):
* runtime/IteratorOperations.cpp:
(JSC::iteratorNext):
(JSC::iteratorStep):
(JSC::iteratorClose):
(JSC::iteratorForIterable):
* runtime/IteratorOperations.h:
(JSC::forEachInIterable):
* runtime/JSArray.cpp:
(JSC::JSArray::pop):
(JSC::JSArray::push):
(JSC::JSArray::copyToArguments):
* runtime/JSArrayBufferConstructor.cpp:
(JSC::constructArrayBuffer):
* runtime/JSArrayBufferPrototype.cpp:
(JSC::arrayBufferProtoFuncSlice):
* runtime/JSArrayInlines.h:
(JSC::getLength):
(JSC::toLength):
* runtime/JSBoundFunction.cpp:
(JSC::getBoundFunctionStructure):
(JSC::JSBoundFunction::create):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::putToPrimitive):
(JSC::JSValue::putToPrimitiveByIndex):
(JSC::JSValue::toStringSlowCase):
* runtime/JSCJSValueInlines.h:
(JSC::toPreferredPrimitiveType):
(JSC::JSValue::getPropertySlot):
(JSC::JSValue::equalSlowCaseInline):
* runtime/JSDataViewPrototype.cpp:
(JSC::getData):
(JSC::setData):
* runtime/JSFunction.cpp:
(JSC::JSFunction::setFunctionName):
* runtime/JSGenericTypedArrayView.h:
(JSC::JSGenericTypedArrayView::setIndex):
* runtime/JSGenericTypedArrayViewConstructorInlines.h:
(JSC::constructGenericTypedArrayViewFromIterator):
(JSC::constructGenericTypedArrayViewWithArguments):
(JSC::constructGenericTypedArrayView):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::speciesConstruct):
(JSC::genericTypedArrayViewProtoFuncCopyWithin):
(JSC::genericTypedArrayViewProtoFuncIncludes):
(JSC::genericTypedArrayViewProtoFuncIndexOf):
(JSC::genericTypedArrayViewProtoFuncJoin):
(JSC::genericTypedArrayViewProtoFuncLastIndexOf):
(JSC::genericTypedArrayViewProtoFuncSlice):
(JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
* runtime/JSGlobalObject.h:
(JSC::constructEmptyArray):
(JSC::constructArray):
(JSC::constructArrayNegativeIndexed):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncEval):
* runtime/JSJob.cpp:
(JSC::JSJobMicrotask::run):
* runtime/JSModuleEnvironment.cpp:
(JSC::JSModuleEnvironment::getOwnPropertySlot):
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::fetch):
* runtime/JSModuleNamespaceObject.cpp:
(JSC::JSModuleNamespaceObject::finishCreation):
(JSC::JSModuleNamespaceObject::getOwnPropertySlot):
* runtime/JSModuleRecord.cpp:
(JSC::JSModuleRecord::instantiateDeclarations):
* runtime/JSONObject.cpp:
(JSC::Stringifier::Stringifier):
(JSC::Stringifier::stringify):
(JSC::Stringifier::toJSON):
(JSC::Stringifier::appendStringifiedValue):
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::Walker::walk):
(JSC::JSONProtoFuncParse):
* runtime/JSObject.cpp:
(JSC::ordinarySetSlow):
(JSC::JSObject::setPrototypeWithCycleCheck):
(JSC::callToPrimitiveFunction):
(JSC::JSObject::ordinaryToPrimitive):
(JSC::JSObject::defaultHasInstance):
(JSC::JSObject::getPropertyNames):
(JSC::JSObject::toNumber):
(JSC::JSObject::toString):
(JSC::JSObject::defineOwnNonIndexProperty):
(JSC::JSObject::getGenericPropertyNames):
(JSC::JSObject::getMethod):
* runtime/JSObjectInlines.h:
(JSC::createListFromArrayLike):
(JSC::JSObject::getPropertySlot):
(JSC::JSObject::getNonIndexPropertySlot):
* runtime/JSPromiseConstructor.cpp:
(JSC::constructPromise):
* runtime/JSPropertyNameEnumerator.h:
(JSC::propertyNameEnumerator):
* runtime/JSPropertyNameIterator.cpp:
(JSC::JSPropertyNameIterator::create):
* runtime/JSScope.cpp:
(JSC::isUnscopable):
(JSC::JSScope::resolve):
* runtime/JSString.cpp:
(JSC::JSString::equalSlowCase):
* runtime/JSStringJoiner.cpp:
(JSC::JSStringJoiner::join):
* runtime/LiteralParser.cpp:
(JSC::LiteralParser<CharType>::parse):
* runtime/MapConstructor.cpp:
(JSC::constructMap):
* runtime/MathObject.cpp:
(JSC::mathProtoFuncClz32):
(JSC::mathProtoFuncHypot):
(JSC::mathProtoFuncIMul):
* runtime/ModuleLoaderPrototype.cpp:
(JSC::moduleLoaderPrototypeParseModule):
(JSC::moduleLoaderPrototypeRequestedModules):
(JSC::moduleLoaderPrototypeModuleDeclarationInstantiation):
* runtime/NativeErrorConstructor.cpp:
(JSC::Interpreter::constructWithNativeErrorConstructor):
* runtime/NumberConstructor.cpp:
(JSC::constructWithNumberConstructor):
* runtime/ObjectConstructor.cpp:
(JSC::constructObject):
(JSC::objectConstructorGetPrototypeOf):
(JSC::objectConstructorSetPrototypeOf):
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorGetOwnPropertyDescriptors):
(JSC::objectConstructorGetOwnPropertyNames):
(JSC::objectConstructorGetOwnPropertySymbols):
(JSC::objectConstructorKeys):
(JSC::ownEnumerablePropertyKeys):
(JSC::toPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
(JSC::defineProperties):
(JSC::objectConstructorSeal):
(JSC::objectConstructorFreeze):
(JSC::objectConstructorIsSealed):
(JSC::objectConstructorIsFrozen):
(JSC::objectConstructorIsExtensible):
(JSC::ownPropertyKeys):
* runtime/ObjectConstructor.h:
(JSC::constructObjectFromPropertyDescriptor):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncHasOwnProperty):
(JSC::objectProtoFuncIsPrototypeOf):
(JSC::objectProtoFuncDefineGetter):
(JSC::objectProtoFuncDefineSetter):
(JSC::objectProtoFuncLookupGetter):
(JSC::objectProtoFuncLookupSetter):
(JSC::objectProtoFuncPropertyIsEnumerable):
(JSC::objectProtoFuncToLocaleString):
(JSC::objectProtoFuncToString):
* runtime/Operations.cpp:
(JSC::jsAddSlowCase):
* runtime/Options.h:
* runtime/PropertyDescriptor.cpp:
(JSC::PropertyDescriptor::slowGetterSetter):
* runtime/ProxyConstructor.cpp:
(JSC::makeRevocableProxy):
* runtime/ProxyObject.cpp:
(JSC::ProxyObject::toStringName):
(JSC::performProxyGet):
(JSC::ProxyObject::performGet):
(JSC::ProxyObject::performInternalMethodGetOwnProperty):
(JSC::ProxyObject::performHasProperty):
(JSC::ProxyObject::performPut):
(JSC::ProxyObject::putByIndexCommon):
(JSC::performProxyCall):
(JSC::performProxyConstruct):
(JSC::ProxyObject::performDelete):
(JSC::ProxyObject::performPreventExtensions):
(JSC::ProxyObject::performIsExtensible):
(JSC::ProxyObject::performDefineOwnProperty):
(JSC::ProxyObject::performGetOwnPropertyNames):
(JSC::ProxyObject::performSetPrototype):
(JSC::ProxyObject::performGetPrototype):
* runtime/ReflectObject.cpp:
(JSC::reflectObjectConstruct):
(JSC::reflectObjectDefineProperty):
(JSC::reflectObjectGet):
(JSC::reflectObjectGetOwnPropertyDescriptor):
(JSC::reflectObjectIsExtensible):
(JSC::reflectObjectPreventExtensions):
(JSC::reflectObjectSet):
(JSC::reflectObjectSetPrototypeOf):
* runtime/RegExpConstructor.cpp:
(JSC::toFlags):
(JSC::regExpCreate):
(JSC::constructRegExp):
* runtime/RegExpConstructor.h:
(JSC::isRegExp):
* runtime/RegExpObject.cpp:
(JSC::collectMatches):
(JSC::RegExpObject::matchGlobal):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
(JSC::flagsString):
(JSC::regExpProtoFuncToString):
(JSC::regExpProtoGetterFlags):
(JSC::regExpProtoFuncSearchFast):
(JSC::regExpProtoFuncSplitFast):
* runtime/SetConstructor.cpp:
(JSC::constructSet):
* runtime/StringConstructor.cpp:
(JSC::stringFromCodePoint):
(JSC::constructWithStringConstructor):
* runtime/StringObject.cpp:
(JSC::StringObject::defineOwnProperty):
* runtime/StringPrototype.cpp:
(JSC::replaceUsingRegExpSearch):
(JSC::operationStringProtoFuncReplaceRegExpEmptyStr):
(JSC::replaceUsingStringSearch):
(JSC::replace):
(JSC::stringProtoFuncReplaceUsingRegExp):
(JSC::stringProtoFuncReplaceUsingStringSearch):
(JSC::stringProtoFuncCodePointAt):
(JSC::stringProtoFuncSlice):
(JSC::stringProtoFuncSplitFast):
(JSC::stringProtoFuncSubstr):
(JSC::stringProtoFuncSubstring):
(JSC::stringProtoFuncLocaleCompare):
(JSC::toLocaleCase):
(JSC::stringProtoFuncBig):
(JSC::stringProtoFuncSmall):
(JSC::stringProtoFuncBlink):
(JSC::stringProtoFuncBold):
(JSC::stringProtoFuncFixed):
(JSC::stringProtoFuncItalics):
(JSC::stringProtoFuncStrike):
(JSC::stringProtoFuncSub):
(JSC::stringProtoFuncSup):
(JSC::stringProtoFuncFontcolor):
(JSC::stringProtoFuncFontsize):
(JSC::stringProtoFuncAnchor):
(JSC::stringProtoFuncLink):
(JSC::trimString):
(JSC::stringProtoFuncStartsWith):
(JSC::stringProtoFuncEndsWith):
(JSC::stringIncludesImpl):
(JSC::stringProtoFuncIncludes):
(JSC::builtinStringIncludesInternal):
(JSC::stringProtoFuncNormalize):
* runtime/SymbolConstructor.cpp:
(JSC::symbolConstructorFor):
* runtime/TemplateRegistry.cpp:
(JSC::TemplateRegistry::getTemplateObject):
* runtime/ThrowScope.cpp:
(JSC::ThrowScope::ThrowScope):
(JSC::ThrowScope::~ThrowScope):
(JSC::ThrowScope::throwException):
(JSC::ThrowScope::simulateThrow):
(JSC::ThrowScope::printIfNeedCheck): Deleted.
(JSC::ThrowScope::verifyExceptionCheckNeedIsSatisfied): Deleted.
* runtime/ThrowScope.h:
(JSC::ThrowScope::release):
(JSC::ThrowScope::ThrowScope):
(JSC::ThrowScope::throwException):
(JSC::ThrowScope::vm): Deleted.
(JSC::ThrowScope::exception): Deleted.
* runtime/ThrowScopeLocation.h: Removed.
* runtime/VM.cpp:
(JSC::VM::verifyExceptionCheckNeedIsSatisfied):
* runtime/VM.h:
(JSC::VM::exception):
(JSC::VM::clearException):
(JSC::VM::setException): Deleted.
* runtime/WeakMapConstructor.cpp:
(JSC::constructWeakMap):
* runtime/WeakSetConstructor.cpp:
(JSC::constructWeakSet):
* tools/JSDollarVMPrototype.cpp:
(JSC::functionPrint):

Source/WebCore:

No new test because there is no behavior change in general except for 1 bug fix.
That bug is already caught by existing tests with the introduction of the CatchScope.

Fixes a bug in JSEventListener::handleEvent() where the exception thrown from
a failed attempt to get the handleEvent callback is not handled.

* ForwardingHeaders/runtime/CatchScope.h: Added.
* Modules/encryptedmedia/CDMSessionClearKey.cpp:
(WebCore::CDMSessionClearKey::update):
* Modules/indexeddb/IDBObjectStore.cpp:
(WebCore::IDBObjectStore::putOrAdd):
* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd):
* Modules/mediastream/SDPProcessor.cpp:
(WebCore::SDPProcessor::callScript):
* Modules/plugins/QuickTimePluginReplacement.mm:
(WebCore::QuickTimePluginReplacement::ensureReplacementScriptInjected):
(WebCore::QuickTimePluginReplacement::installReplacement):
* bindings/js/ArrayValue.cpp:
(WebCore::ArrayValue::get):
* bindings/js/Dictionary.cpp:
(WebCore::Dictionary::getOwnPropertiesAsStringHashMap):
* bindings/js/IDBBindingUtilities.cpp:
(WebCore::toJS):
* bindings/js/JSApplePaySessionCustom.cpp:
(WebCore::JSApplePaySession::completeShippingMethodSelection):
(WebCore::JSApplePaySession::completeShippingContactSelection):
(WebCore::JSApplePaySession::completePaymentMethodSelection):
* bindings/js/JSAudioTrackCustom.cpp:
(WebCore::JSAudioTrack::setKind):
(WebCore::JSAudioTrack::setLanguage):
* bindings/js/JSBlobCustom.cpp:
(WebCore::constructJSBlob):
* bindings/js/JSCSSStyleDeclarationCustom.cpp:
(WebCore::JSCSSStyleDeclaration::getPropertyCSSValue):
* bindings/js/JSCommandLineAPIHostCustom.cpp:
(WebCore::getJSListenerFunctions):
* bindings/js/JSCryptoAlgorithmDictionary.cpp:
(WebCore::JSCryptoAlgorithmDictionary::getAlgorithmIdentifier):
(WebCore::getHashAlgorithm):
(WebCore::createAesCbcParams):
(WebCore::createAesKeyGenParams):
(WebCore::createHmacParams):
(WebCore::createHmacKeyParams):
(WebCore::createRsaKeyGenParams):
(WebCore::createRsaOaepParams):
(WebCore::createRsaSsaParams):
* bindings/js/JSCryptoKeySerializationJWK.cpp:
(WebCore::getJSArrayFromJSON):
(WebCore::getStringFromJSON):
(WebCore::getBooleanFromJSON):
(WebCore::JSCryptoKeySerializationJWK::JSCryptoKeySerializationJWK):
(WebCore::JSCryptoKeySerializationJWK::reconcileUsages):
(WebCore::JSCryptoKeySerializationJWK::keyDataOctetSequence):
(WebCore::JSCryptoKeySerializationJWK::keyDataRSAComponents):
(WebCore::JSCryptoKeySerializationJWK::keyData):
(WebCore::buildJSONForRSAComponents):
(WebCore::addUsagesToJSON):
(WebCore::JSCryptoKeySerializationJWK::serialize):
* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::constructElement):
(WebCore::constructCustomElementSynchronously):
(WebCore::JSCustomElementInterface::upgradeElement):
* bindings/js/JSCustomElementRegistryCustom.cpp:
(WebCore::getCustomElementCallback):
(WebCore::JSCustomElementRegistry::define):
(WebCore::whenDefinedPromise):
(WebCore::JSCustomElementRegistry::whenDefined):
* bindings/js/JSDOMBinding.cpp:
(WebCore::valueToUSVString):
(WebCore::reportException):
(WebCore::reportCurrentException):
(WebCore::setDOMException):
(WebCore::hasIteratorMethod):
(WebCore::toSmallerInt):
(WebCore::toSmallerUInt):
(WebCore::toInt32EnforceRange):
(WebCore::toUInt32EnforceRange):
(WebCore::toInt64EnforceRange):
(WebCore::toUInt64EnforceRange):
(WebCore::throwNotSupportedError):
(WebCore::throwInvalidStateError):
(WebCore::throwSecurityError):
* bindings/js/JSDOMBinding.h:
(WebCore::toJSSequence):
(WebCore::toJS):
(WebCore::jsFrozenArray):
(WebCore::NativeValueTraits<String>::nativeValue):
(WebCore::NativeValueTraits<unsigned>::nativeValue):
(WebCore::NativeValueTraits<float>::nativeValue):
(WebCore::NativeValueTraits<double>::nativeValue):
(WebCore::toNativeArray):
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::makeThisTypeErrorForBuiltins):
(WebCore::makeGetterTypeErrorForBuiltins):
* bindings/js/JSDOMGlobalObjectTask.cpp:
* bindings/js/JSDOMIterator.h:
(WebCore::iteratorForEach):
* bindings/js/JSDOMPromise.cpp:
(WebCore::rejectPromiseWithExceptionIfAny):
* bindings/js/JSDOMPromise.h:
(WebCore::callPromiseFunction):
* bindings/js/JSDOMStringMapCustom.cpp:
(WebCore::JSDOMStringMap::putDelegate):
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowMicrotaskCallback::call):
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::setLocation):
(WebCore::JSDOMWindow::open):
(WebCore::JSDOMWindow::showModalDialog):
(WebCore::handlePostMessage):
(WebCore::JSDOMWindow::setTimeout):
(WebCore::JSDOMWindow::setInterval):
* bindings/js/JSDataCueCustom.cpp:
(WebCore::constructJSDataCue):
* bindings/js/JSDeviceMotionEventCustom.cpp:
(WebCore::readAccelerationArgument):
(WebCore::readRotationRateArgument):
(WebCore::JSDeviceMotionEvent::initDeviceMotionEvent):
* bindings/js/JSDictionary.cpp:
(WebCore::JSDictionary::tryGetProperty):
(WebCore::JSDictionary::convertValue):
* bindings/js/JSDictionary.h:
(WebCore::JSDictionary::tryGetPropertyAndResult):
* bindings/js/JSDocumentCustom.cpp:
(WebCore::JSDocument::getCSSCanvasContext):
* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::handleEvent):
* bindings/js/JSFileCustom.cpp:
(WebCore::constructJSFile):
* bindings/js/JSGeolocationCustom.cpp:
(WebCore::createPositionOptions):
(WebCore::JSGeolocation::getCurrentPosition):
(WebCore::JSGeolocation::watchPosition):
* bindings/js/JSHTMLAllCollectionCustom.cpp:
(WebCore::callHTMLAllCollection):
* bindings/js/JSHTMLCanvasElementCustom.cpp:
(WebCore::get3DContextAttributes):
(WebCore::JSHTMLCanvasElement::getContext):
(WebCore::JSHTMLCanvasElement::probablySupportsContext):
* bindings/js/JSHTMLElementCustom.cpp:
(WebCore::constructJSHTMLElement):
* bindings/js/JSHistoryCustom.cpp:
(WebCore::JSHistory::pushState):
(WebCore::JSHistory::replaceState):
* bindings/js/JSIDBDatabaseCustom.cpp:
(WebCore::JSIDBDatabase::createObjectStore):
* bindings/js/JSLazyEventListener.cpp:
(WebCore::JSLazyEventListener::initializeJSFunction):
* bindings/js/JSMainThreadExecState.h:
(WebCore::JSMainThreadExecState::linkAndEvaluateModule):
(WebCore::JSMainThreadExecState::~JSMainThreadExecState):
* bindings/js/JSMessageEventCustom.cpp:
(WebCore::handleInitMessageEvent):
* bindings/js/JSMessagePortCustom.cpp:
(WebCore::fillMessagePortArray):
* bindings/js/JSMessagePortCustom.h:
(WebCore::handlePostMessage):
* bindings/js/JSMockContentFilterSettingsCustom.cpp:
(WebCore::JSMockContentFilterSettings::setDecisionPoint):
(WebCore::toDecision):
(WebCore::JSMockContentFilterSettings::setDecision):
(WebCore::JSMockContentFilterSettings::setUnblockRequestDecision):
* bindings/js/JSNodeFilterCustom.cpp:
(WebCore::JSNodeFilter::acceptNode):
* bindings/js/JSNodeOrString.cpp:
(WebCore::toNodeOrStringVector):
* bindings/js/JSSQLTransactionCustom.cpp:
(WebCore::JSSQLTransaction::executeSql):
* bindings/js/JSSVGLengthCustom.cpp:
(WebCore::JSSVGLength::convertToSpecifiedUnits):
* bindings/js/JSStorageCustom.cpp:
(WebCore::JSStorage::getOwnPropertyNames):
(WebCore::JSStorage::putDelegate):
* bindings/js/JSTextTrackCustom.cpp:
(WebCore::JSTextTrack::setLanguage):
* bindings/js/JSVideoTrackCustom.cpp:
(WebCore::JSVideoTrack::setKind):
(WebCore::JSVideoTrack::setLanguage):
* bindings/js/JSWebGL2RenderingContextCustom.cpp:
(WebCore::JSWebGL2RenderingContext::getIndexedParameter):
* bindings/js/JSWebGLRenderingContextBaseCustom.cpp:
(WebCore::getObjectParameter):
(WebCore::JSWebGLRenderingContextBase::getExtension):
(WebCore::JSWebGLRenderingContextBase::getFramebufferAttachmentParameter):
(WebCore::JSWebGLRenderingContextBase::getParameter):
(WebCore::JSWebGLRenderingContextBase::getProgramParameter):
(WebCore::JSWebGLRenderingContextBase::getShaderParameter):
(WebCore::toVector):
(WebCore::dataFunctionf):
(WebCore::dataFunctionMatrix):
* bindings/js/JSWebKitSubtleCryptoCustom.cpp:
(WebCore::createAlgorithmFromJSValue):
(WebCore::cryptoKeyFormatFromJSValue):
(WebCore::cryptoKeyUsagesFromJSValue):
(WebCore::JSWebKitSubtleCrypto::encrypt):
(WebCore::JSWebKitSubtleCrypto::decrypt):
(WebCore::JSWebKitSubtleCrypto::sign):
(WebCore::JSWebKitSubtleCrypto::verify):
(WebCore::JSWebKitSubtleCrypto::digest):
(WebCore::JSWebKitSubtleCrypto::generateKey):
(WebCore::importKey):
(WebCore::JSWebKitSubtleCrypto::importKey):
(WebCore::exportKey):
(WebCore::JSWebKitSubtleCrypto::exportKey):
(WebCore::JSWebKitSubtleCrypto::wrapKey):
(WebCore::JSWebKitSubtleCrypto::unwrapKey):
* bindings/js/JSWorkerCustom.cpp:
(WebCore::constructJSWorker):
* bindings/js/JSWorkerGlobalScopeCustom.cpp:
(WebCore::JSWorkerGlobalScope::importScripts):
(WebCore::JSWorkerGlobalScope::setTimeout):
(WebCore::JSWorkerGlobalScope::setInterval):
* bindings/js/ReadableStreamDefaultController.cpp:
(WebCore::ReadableStreamDefaultController::invoke):
(WebCore::ReadableStreamDefaultController::isControlledReadableStreamLocked):
* bindings/js/ReadableStreamDefaultController.h:
(WebCore::ReadableStreamDefaultController::enqueue):
* bindings/js/ScheduledAction.cpp:
(WebCore::ScheduledAction::create):
* bindings/js/ScriptGlobalObject.cpp:
(WebCore::ScriptGlobalObject::set):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneBase::shouldTerminate):
(WebCore::CloneDeserializer::deserialize):
(WebCore::SerializedScriptValue::create):
(WebCore::SerializedScriptValue::deserialize):
* bindings/js/WorkerScriptController.cpp:
(WebCore::WorkerScriptController::evaluate):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateDictionaryImplementationContent):
(GenerateImplementation):
(GenerateParametersCheck):
(GenerateImplementationFunctionCall):
(GenerateConstructorDefinition):
* bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:
(WebCore::jsTestActiveDOMObjectPrototypeFunctionPostMessage):
* bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp:
(WebCore::jsTestCustomNamedGetterPrototypeFunctionAnotherFunction):
* bindings/scripts/test/JS/JSTestEventConstructor.cpp:
(WebCore::JSTestEventConstructorConstructor::construct):
* bindings/scripts/test/JS/JSTestEventTarget.cpp:
(WebCore::jsTestEventTargetPrototypeFunctionItem):
* bindings/scripts/test/JS/JSTestGlobalObject.cpp:
(WebCore::setJSTestGlobalObjectRegularAttribute):
(WebCore::setJSTestGlobalObjectPublicAndPrivateAttribute):
(WebCore::setJSTestGlobalObjectPublicAndPrivateConditionalAttribute):
(WebCore::setJSTestGlobalObjectEnabledAtRuntimeAttribute):
(WebCore::jsTestGlobalObjectInstanceFunctionRegularOperation):
(WebCore::jsTestGlobalObjectInstanceFunctionEnabledAtRuntimeOperation1):
(WebCore::jsTestGlobalObjectInstanceFunctionEnabledAtRuntimeOperation2):
* bindings/scripts/test/JS/JSTestInterface.cpp:
(WebCore::JSTestInterfaceConstructor::construct):
(WebCore::setJSTestInterfaceConstructorImplementsStaticAttr):
(WebCore::setJSTestInterfaceImplementsStr2):
(WebCore::setJSTestInterfaceImplementsStr3):
(WebCore::setJSTestInterfaceImplementsNode):
(WebCore::setJSTestInterfaceConstructorSupplementalStaticAttr):
(WebCore::setJSTestInterfaceSupplementalStr2):
(WebCore::setJSTestInterfaceSupplementalStr3):
(WebCore::setJSTestInterfaceSupplementalNode):
(WebCore::jsTestInterfacePrototypeFunctionImplementsMethod2):
(WebCore::jsTestInterfacePrototypeFunctionSupplementalMethod2):
* bindings/scripts/test/JS/JSTestJSBuiltinConstructor.cpp:
(WebCore::setJSTestJSBuiltinConstructorTestAttributeRWCustom):
* bindings/scripts/test/JS/JSTestNamedConstructor.cpp:
(WebCore::JSTestNamedConstructorNamedConstructor::construct):
* bindings/scripts/test/JS/JSTestNode.cpp:
(WebCore::setJSTestNodeName):
* bindings/scripts/test/JS/JSTestNondeterministic.cpp:
(WebCore::setJSTestNondeterministicNondeterministicWriteableAttr):
(WebCore::setJSTestNondeterministicNondeterministicExceptionAttr):
(WebCore::setJSTestNondeterministicNondeterministicGetterExceptionAttr):
(WebCore::setJSTestNondeterministicNondeterministicSetterExceptionAttr):
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::convertDictionary<TestObj::Dictionary>):
(WebCore::convertDictionary<TestObj::DictionaryThatShouldNotTolerateNull>):
(WebCore::convertDictionary<TestObj::DictionaryThatShouldTolerateNull>):
(WebCore::convertDictionary<AlternateDictionaryName>):
(WebCore::setJSTestObjConstructorStaticStringAttr):
(WebCore::setJSTestObjTestSubObjEnabledBySettingConstructor):
(WebCore::setJSTestObjEnumAttr):
(WebCore::setJSTestObjByteAttr):
(WebCore::setJSTestObjOctetAttr):
(WebCore::setJSTestObjShortAttr):
(WebCore::setJSTestObjClampedShortAttr):
(WebCore::setJSTestObjEnforceRangeShortAttr):
(WebCore::setJSTestObjUnsignedShortAttr):
(WebCore::setJSTestObjLongAttr):
(WebCore::setJSTestObjLongLongAttr):
(WebCore::setJSTestObjUnsignedLongLongAttr):
(WebCore::setJSTestObjStringAttr):
(WebCore::setJSTestObjUsvstringAttr):
(WebCore::setJSTestObjTestObjAttr):
(WebCore::setJSTestObjTestNullableObjAttr):
(WebCore::setJSTestObjLenientTestObjAttr):
(WebCore::setJSTestObjStringAttrTreatingNullAsEmptyString):
(WebCore::setJSTestObjUsvstringAttrTreatingNullAsEmptyString):
(WebCore::setJSTestObjImplementationEnumAttr):
(WebCore::setJSTestObjXMLObjAttr):
(WebCore::setJSTestObjCreate):
(WebCore::setJSTestObjReflectedStringAttr):
(WebCore::setJSTestObjReflectedUSVStringAttr):
(WebCore::setJSTestObjReflectedIntegralAttr):
(WebCore::setJSTestObjReflectedUnsignedIntegralAttr):
(WebCore::setJSTestObjReflectedBooleanAttr):
(WebCore::setJSTestObjReflectedURLAttr):
(WebCore::setJSTestObjReflectedUSVURLAttr):
(WebCore::setJSTestObjReflectedCustomIntegralAttr):
(WebCore::setJSTestObjReflectedCustomBooleanAttr):
(WebCore::setJSTestObjReflectedCustomURLAttr):
(WebCore::setJSTestObjEnabledAtRuntimeAttribute):
(WebCore::setJSTestObjTypedArrayAttr):
(WebCore::setJSTestObjAttrWithGetterException):
(WebCore::setJSTestObjAttrWithGetterExceptionWithMessage):
(WebCore::setJSTestObjAttrWithSetterException):
(WebCore::setJSTestObjAttrWithSetterExceptionWithMessage):
(WebCore::setJSTestObjStringAttrWithGetterException):
(WebCore::setJSTestObjStringAttrWithSetterException):
(WebCore::setJSTestObjCustomAttr):
(WebCore::setJSTestObjOnfoo):
(WebCore::setJSTestObjOnwebkitfoo):
(WebCore::setJSTestObjWithScriptStateAttribute):
(WebCore::setJSTestObjWithCallWithAndSetterCallWithAttribute):
(WebCore::setJSTestObjWithScriptExecutionContextAttribute):
(WebCore::setJSTestObjWithScriptStateAttributeRaises):
(WebCore::setJSTestObjWithScriptExecutionContextAttributeRaises):
(WebCore::setJSTestObjWithScriptExecutionContextAndScriptStateAttribute):
(WebCore::setJSTestObjWithScriptExecutionContextAndScriptStateAttributeRaises):
(WebCore::setJSTestObjWithScriptExecutionContextAndScriptStateWithSpacesAttribute):
(WebCore::setJSTestObjWithScriptArgumentsAndCallStackAttribute):
(WebCore::setJSTestObjConditionalAttr1):
(WebCore::setJSTestObjConditionalAttr2):
(WebCore::setJSTestObjConditionalAttr3):
(WebCore::setJSTestObjConditionalAttr4Constructor):
(WebCore::setJSTestObjConditionalAttr5Constructor):
(WebCore::setJSTestObjConditionalAttr6Constructor):
(WebCore::setJSTestObjAnyAttribute):
(WebCore::setJSTestObjMutablePoint):
(WebCore::setJSTestObjImmutablePoint):
(WebCore::setJSTestObjStrawberry):
(WebCore::setJSTestObjId):
(WebCore::setJSTestObjReplaceableAttribute):
(WebCore::setJSTestObjNullableLongSettableAttribute):
(WebCore::setJSTestObjNullableStringSettableAttribute):
(WebCore::setJSTestObjNullableUSVStringSettableAttribute):
(WebCore::setJSTestObjNullableStringValue):
(WebCore::setJSTestObjAttributeWithReservedEnumType):
(WebCore::setJSTestObjPutForwardsAttribute):
(WebCore::setJSTestObjPutForwardsNullableAttribute):
(WebCore::setJSTestObjStringifierAttribute):
(WebCore::jsTestObjPrototypeFunctionEnabledAtRuntimeOperation1):
(WebCore::jsTestObjPrototypeFunctionEnabledAtRuntimeOperation2):
(WebCore::jsTestObjPrototypeFunctionVoidMethodWithArgs):
(WebCore::jsTestObjPrototypeFunctionByteMethodWithArgs):
(WebCore::jsTestObjPrototypeFunctionOctetMethodWithArgs):
(WebCore::jsTestObjPrototypeFunctionLongMethodWithArgs):
(WebCore::jsTestObjPrototypeFunctionObjMethodWithArgs):
(WebCore::jsTestObjPrototypeFunctionMethodWithArgTreatingNullAsEmptyString):
(WebCore::jsTestObjPrototypeFunctionMethodWithXPathNSResolverParameter):
(WebCore::jsTestObjPrototypeFunctionNullableStringSpecialMethod):
(WebCore::jsTestObjPrototypeFunctionMethodWithEnumArg):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalEnumArg):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalEnumArgAndDefaultValue):
(WebCore::jsTestObjPrototypeFunctionMethodThatRequiresAllArgsAndThrows):
(WebCore::jsTestObjPrototypeFunctionMethodWithUSVStringArg):
(WebCore::jsTestObjPrototypeFunctionMethodWithNullableUSVStringArg):
(WebCore::jsTestObjPrototypeFunctionMethodWithUSVStringArgTreatingNullAsEmptyString):
(WebCore::jsTestObjPrototypeFunctionSerializedValue):
(WebCore::jsTestObjPrototypeFunctionPrivateMethod):
(WebCore::jsTestObjPrototypeFunctionPublicAndPrivateMethod):
(WebCore::jsTestObjPrototypeFunctionAddEventListener):
(WebCore::jsTestObjPrototypeFunctionRemoveEventListener):
(WebCore::jsTestObjPrototypeFunctionWithScriptStateObj):
(WebCore::jsTestObjPrototypeFunctionWithScriptStateObjException):
(WebCore::jsTestObjPrototypeFunctionWithScriptExecutionContextAndScriptStateObjException):
(WebCore::jsTestObjPrototypeFunctionWithScriptExecutionContextAndScriptStateWithSpaces):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalArg):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalArgAndDefaultValue):
(WebCore::jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndOptionalArg):
(WebCore::jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndTwoOptionalArgs):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalString):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalUSVString):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalAtomicString):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalStringAndDefaultValue):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalAtomicStringAndDefaultValue):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalStringIsNull):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalStringIsUndefined):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalAtomicStringIsNull):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalStringIsEmptyString):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalUSVStringIsEmptyString):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalAtomicStringIsEmptyString):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalDoubleIsNaN):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalFloatIsNaN):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalLongLong):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalLongLongIsZero):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalUnsignedLongLong):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalUnsignedLongLongIsZero):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalSequence):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalSequenceIsEmpty):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalBoolean):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalBooleanIsFalse):
(WebCore::jsTestObjPrototypeFunctionMethodWithOptionalXPathNSResolver):
(WebCore::jsTestObjPrototypeFunctionMethodWithNonCallbackArgAndCallbackArg):
(WebCore::jsTestObjPrototypeFunctionMethodWithNonCallbackArgAndCallbackFunctionArg):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethod1):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethod2):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethod3):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethod4):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethod7):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethod9):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethod10):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethod11):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter1):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter2):
(WebCore::jsTestObjConstructorFunctionClassMethodWithOptional):
(WebCore::jsTestObjConstructorFunctionOverloadedMethod11):
(WebCore::jsTestObjConstructorFunctionOverloadedMethod12):
(WebCore::jsTestObjPrototypeFunctionClassMethodWithClamp):
(WebCore::jsTestObjPrototypeFunctionClassMethodWithEnforceRange):
(WebCore::jsTestObjPrototypeFunctionMethodWithUnsignedLongSequence):
(WebCore::jsTestObjPrototypeFunctionStringArrayFunction):
(WebCore::jsTestObjPrototypeFunctionMethodWithAndWithoutNullableSequence):
(WebCore::jsTestObjPrototypeFunctionGetElementById):
(WebCore::jsTestObjPrototypeFunctionConvert3):
(WebCore::jsTestObjPrototypeFunctionConvert4):
(WebCore::jsTestObjPrototypeFunctionVariadicStringMethod):
(WebCore::jsTestObjPrototypeFunctionVariadicDoubleMethod):
(WebCore::jsTestObjPrototypeFunctionAny):
(WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgumentPromise):
(WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithOptionalIntArgumentPromise):
(WebCore::jsTestObjPrototypeFunctionTestPromiseOverloadedFunction1Promise):
(WebCore::jsTestObjPrototypeFunctionConditionalOverload1):
(WebCore::jsTestObjPrototypeFunctionConditionalOverload2):
(WebCore::jsTestObjPrototypeFunctionSingleConditionalOverload1):
(WebCore::jsTestObjPrototypeFunctionSingleConditionalOverload2):
(WebCore::jsTestObjPrototypeFunctionAttachShadowRoot):
* bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
(WebCore::constructJSTestOverloadedConstructors1):
(WebCore::constructJSTestOverloadedConstructors2):
(WebCore::constructJSTestOverloadedConstructors4):
(WebCore::constructJSTestOverloadedConstructors5):
* bindings/scripts/test/JS/JSTestOverloadedConstructorsWithSequence.cpp:
(WebCore::constructJSTestOverloadedConstructorsWithSequence1):
(WebCore::constructJSTestOverloadedConstructorsWithSequence2):
* bindings/scripts/test/JS/JSTestOverrideBuiltins.cpp:
(WebCore::jsTestOverrideBuiltinsPrototypeFunctionNamedItem):
* bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:
(WebCore::setJSTestSerializedScriptValueInterfaceValue):
(WebCore::setJSTestSerializedScriptValueInterfaceCachedValue):
* bindings/scripts/test/JS/JSTestTypedefs.cpp:
(WebCore::JSTestTypedefsConstructor::construct):
(WebCore::setJSTestTypedefsUnsignedLongLongAttr):
(WebCore::setJSTestTypedefsImmutableSerializedScriptValue):
(WebCore::setJSTestTypedefsAttrWithGetterException):
(WebCore::setJSTestTypedefsAttrWithSetterException):
(WebCore::setJSTestTypedefsStringAttrWithGetterException):
(WebCore::setJSTestTypedefsStringAttrWithSetterException):
(WebCore::jsTestTypedefsPrototypeFunctionFunc):
(WebCore::jsTestTypedefsPrototypeFunctionSetShadow):
(WebCore::jsTestTypedefsPrototypeFunctionMethodWithSequenceArg):
(WebCore::jsTestTypedefsPrototypeFunctionNullableSequenceArg):
(WebCore::jsTestTypedefsPrototypeFunctionFuncWithClamp):
(WebCore::jsTestTypedefsPrototypeFunctionStringSequenceFunction):
(WebCore::jsTestTypedefsPrototypeFunctionStringSequenceFunction2):
(WebCore::jsTestTypedefsPrototypeFunctionCallWithSequenceThatRequiresInclude):
* bridge/NP_jsobject.cpp:
(_NPN_InvokeDefault):
(_NPN_Invoke):
(_NPN_Evaluate):
(_NPN_GetProperty):
(_NPN_SetProperty):
(_NPN_RemoveProperty):
(_NPN_HasProperty):
(_NPN_HasMethod):
(_NPN_Enumerate):
(_NPN_Construct):
* bridge/c/c_instance.cpp:
(JSC::Bindings::CInstance::moveGlobalExceptionToExecState):
* bridge/objc/WebScriptObject.mm:
(WebCore::addExceptionToConsole):
(-[WebScriptObject callWebScriptMethod:withArguments:]):
(-[WebScriptObject evaluateWebScript:]):
(-[WebScriptObject setValue:forKey:]):
(-[WebScriptObject valueForKey:]):
(-[WebScriptObject removeWebScriptKey:]):
(-[WebScriptObject hasWebScriptKey:]):
(-[WebScriptObject webScriptValueAtIndex:]):
(-[WebScriptObject setWebScriptValueAtIndex:value:]):
* contentextensions/ContentExtensionParser.cpp:
(WebCore::ContentExtensions::getDomainList):
(WebCore::ContentExtensions::getTypeFlags):
(WebCore::ContentExtensions::loadTrigger):
(WebCore::ContentExtensions::loadAction):
(WebCore::ContentExtensions::loadEncodedRules):
* html/HTMLMediaElement.cpp:
(WebCore::controllerJSValue):
(WebCore::HTMLMediaElement::updateCaptionContainer):
(WebCore::HTMLMediaElement::ensureMediaControlsInjectedScript):
(WebCore::HTMLMediaElement::didAddUserAgentShadowRoot):
(WebCore::HTMLMediaElement::updateMediaControlsAfterPresentationModeChange):
(WebCore::HTMLMediaElement::getCurrentMediaControlsStatus):
* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::didAddUserAgentShadowRoot):

Source/WebKit/mac:

* Plugins/Hosted/NetscapePluginInstanceProxy.mm:
(WebKit::NetscapePluginInstanceProxy::evaluate):
(WebKit::NetscapePluginInstanceProxy::invoke):
(WebKit::NetscapePluginInstanceProxy::invokeDefault):
(WebKit::NetscapePluginInstanceProxy::construct):
(WebKit::NetscapePluginInstanceProxy::getProperty):
(WebKit::NetscapePluginInstanceProxy::setProperty):
(WebKit::NetscapePluginInstanceProxy::removeProperty):
(WebKit::NetscapePluginInstanceProxy::hasProperty):
(WebKit::NetscapePluginInstanceProxy::hasMethod):
(WebKit::NetscapePluginInstanceProxy::enumerate):
* WebView/WebView.mm:
(aeDescFromJSValue):

Source/WebKit/win:

* Plugins/PluginPackage.cpp:
(WebCore::NPN_Evaluate):
(WebCore::NPN_Invoke):

Source/WebKit2:

* WebProcess/Plugins/Netscape/NPJSObject.cpp:
(WebKit::NPJSObject::hasMethod):
(WebKit::NPJSObject::hasProperty):
(WebKit::NPJSObject::getProperty):
(WebKit::NPJSObject::setProperty):
(WebKit::NPJSObject::removeProperty):
(WebKit::NPJSObject::construct):
(WebKit::NPJSObject::invoke):

Source/WTF:

* wtf/Platform.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@205569 268f45cc-cd09-0410-ab3c-d52691b4dbfc

228 files changed:
Source/JavaScriptCore/API/APIUtils.h
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp
Source/JavaScriptCore/bindings/ScriptValue.cpp
Source/JavaScriptCore/debugger/Debugger.cpp
Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/inspector/InjectedScriptManager.cpp
Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.cpp
Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp
Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp
Source/JavaScriptCore/interpreter/CachedCall.h
Source/JavaScriptCore/interpreter/CallFrame.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/Interpreter.h
Source/JavaScriptCore/interpreter/ShadowChicken.cpp
Source/JavaScriptCore/jit/JITCode.cpp
Source/JavaScriptCore/jit/JITExceptions.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/llint/LLIntExceptions.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/BooleanConstructor.cpp
Source/JavaScriptCore/runtime/CallData.cpp
Source/JavaScriptCore/runtime/CatchScope.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/CatchScope.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.h
Source/JavaScriptCore/runtime/CommonSlowPathsExceptions.cpp
Source/JavaScriptCore/runtime/Completion.cpp
Source/JavaScriptCore/runtime/ConsoleObject.cpp
Source/JavaScriptCore/runtime/DateConstructor.cpp
Source/JavaScriptCore/runtime/DatePrototype.cpp
Source/JavaScriptCore/runtime/ErrorConstructor.cpp
Source/JavaScriptCore/runtime/ErrorInstance.cpp
Source/JavaScriptCore/runtime/ErrorPrototype.cpp
Source/JavaScriptCore/runtime/ExceptionEventLocation.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/ExceptionEventLocation.h [moved from Source/JavaScriptCore/runtime/ThrowScopeLocation.h with 84% similarity]
Source/JavaScriptCore/runtime/ExceptionHelpers.h
Source/JavaScriptCore/runtime/ExceptionScope.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/ExceptionScope.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/FunctionConstructor.cpp
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Source/JavaScriptCore/runtime/GenericArgumentsInlines.h
Source/JavaScriptCore/runtime/GetterSetter.cpp
Source/JavaScriptCore/runtime/InspectorInstrumentationObject.cpp
Source/JavaScriptCore/runtime/InternalFunction.cpp
Source/JavaScriptCore/runtime/IntlCollator.cpp
Source/JavaScriptCore/runtime/IntlCollatorConstructor.cpp
Source/JavaScriptCore/runtime/IntlCollatorPrototype.cpp
Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
Source/JavaScriptCore/runtime/IntlDateTimeFormatConstructor.cpp
Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp
Source/JavaScriptCore/runtime/IntlNumberFormat.cpp
Source/JavaScriptCore/runtime/IntlNumberFormatConstructor.cpp
Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp
Source/JavaScriptCore/runtime/IntlObject.cpp
Source/JavaScriptCore/runtime/IntlObjectInlines.h
Source/JavaScriptCore/runtime/IteratorOperations.cpp
Source/JavaScriptCore/runtime/IteratorOperations.h
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSArrayBufferConstructor.cpp
Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp
Source/JavaScriptCore/runtime/JSArrayInlines.h
Source/JavaScriptCore/runtime/JSBoundFunction.cpp
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSCJSValueInlines.h
Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
Source/JavaScriptCore/runtime/JSJob.cpp
Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp
Source/JavaScriptCore/runtime/JSModuleLoader.cpp
Source/JavaScriptCore/runtime/JSModuleNamespaceObject.cpp
Source/JavaScriptCore/runtime/JSModuleRecord.cpp
Source/JavaScriptCore/runtime/JSONObject.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObjectInlines.h
Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp
Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h
Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
Source/JavaScriptCore/runtime/JSScope.cpp
Source/JavaScriptCore/runtime/JSString.cpp
Source/JavaScriptCore/runtime/JSStringJoiner.cpp
Source/JavaScriptCore/runtime/LiteralParser.cpp
Source/JavaScriptCore/runtime/MapConstructor.cpp
Source/JavaScriptCore/runtime/MathObject.cpp
Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp
Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
Source/JavaScriptCore/runtime/NumberConstructor.cpp
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/ObjectConstructor.h
Source/JavaScriptCore/runtime/ObjectPrototype.cpp
Source/JavaScriptCore/runtime/Operations.cpp
Source/JavaScriptCore/runtime/Options.h
Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
Source/JavaScriptCore/runtime/ProxyConstructor.cpp
Source/JavaScriptCore/runtime/ProxyObject.cpp
Source/JavaScriptCore/runtime/ReflectObject.cpp
Source/JavaScriptCore/runtime/RegExpConstructor.cpp
Source/JavaScriptCore/runtime/RegExpConstructor.h
Source/JavaScriptCore/runtime/RegExpObject.cpp
Source/JavaScriptCore/runtime/RegExpPrototype.cpp
Source/JavaScriptCore/runtime/SetConstructor.cpp
Source/JavaScriptCore/runtime/StringConstructor.cpp
Source/JavaScriptCore/runtime/StringObject.cpp
Source/JavaScriptCore/runtime/StringPrototype.cpp
Source/JavaScriptCore/runtime/SymbolConstructor.cpp
Source/JavaScriptCore/runtime/TemplateRegistry.cpp
Source/JavaScriptCore/runtime/ThrowScope.cpp
Source/JavaScriptCore/runtime/ThrowScope.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/runtime/WeakMapConstructor.cpp
Source/JavaScriptCore/runtime/WeakSetConstructor.cpp
Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/Platform.h
Source/WebCore/ChangeLog
Source/WebCore/ForwardingHeaders/runtime/CatchScope.h [new file with mode: 0644]
Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
Source/WebCore/Modules/mediastream/SDPProcessor.cpp
Source/WebCore/Modules/plugins/QuickTimePluginReplacement.mm
Source/WebCore/bindings/js/ArrayValue.cpp
Source/WebCore/bindings/js/Dictionary.cpp
Source/WebCore/bindings/js/IDBBindingUtilities.cpp
Source/WebCore/bindings/js/JSApplePaySessionCustom.cpp
Source/WebCore/bindings/js/JSAudioTrackCustom.cpp
Source/WebCore/bindings/js/JSBlobCustom.cpp
Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp
Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp
Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp
Source/WebCore/bindings/js/JSCustomElementInterface.cpp
Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp
Source/WebCore/bindings/js/JSDOMBinding.cpp
Source/WebCore/bindings/js/JSDOMBinding.h
Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp
Source/WebCore/bindings/js/JSDOMIterator.h
Source/WebCore/bindings/js/JSDOMPromise.cpp
Source/WebCore/bindings/js/JSDOMPromise.h
Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
Source/WebCore/bindings/js/JSDataCueCustom.cpp
Source/WebCore/bindings/js/JSDeviceMotionEventCustom.cpp
Source/WebCore/bindings/js/JSDictionary.cpp
Source/WebCore/bindings/js/JSDictionary.h
Source/WebCore/bindings/js/JSDocumentCustom.cpp
Source/WebCore/bindings/js/JSEventListener.cpp
Source/WebCore/bindings/js/JSFileCustom.cpp
Source/WebCore/bindings/js/JSGeolocationCustom.cpp
Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp
Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp
Source/WebCore/bindings/js/JSHTMLElementCustom.cpp
Source/WebCore/bindings/js/JSHistoryCustom.cpp
Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp
Source/WebCore/bindings/js/JSLazyEventListener.cpp
Source/WebCore/bindings/js/JSMainThreadExecState.h
Source/WebCore/bindings/js/JSMessageEventCustom.cpp
Source/WebCore/bindings/js/JSMessagePortCustom.cpp
Source/WebCore/bindings/js/JSMessagePortCustom.h
Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp
Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
Source/WebCore/bindings/js/JSNodeOrString.cpp
Source/WebCore/bindings/js/JSSQLTransactionCustom.cpp
Source/WebCore/bindings/js/JSSVGLengthCustom.cpp
Source/WebCore/bindings/js/JSStorageCustom.cpp
Source/WebCore/bindings/js/JSTextTrackCustom.cpp
Source/WebCore/bindings/js/JSVideoTrackCustom.cpp
Source/WebCore/bindings/js/JSWebGL2RenderingContextCustom.cpp
Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp
Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp
Source/WebCore/bindings/js/JSWorkerCustom.cpp
Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp
Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp
Source/WebCore/bindings/js/ReadableStreamDefaultController.h
Source/WebCore/bindings/js/ScheduledAction.cpp
Source/WebCore/bindings/js/ScriptGlobalObject.cpp
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/bindings/js/WorkerScriptController.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestEventTarget.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestGlobalObject.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestJSBuiltinConstructor.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestNamedConstructor.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestNondeterministic.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestOverloadedConstructorsWithSequence.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestOverrideBuiltins.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestTypedefs.cpp
Source/WebCore/bridge/NP_jsobject.cpp
Source/WebCore/bridge/c/c_instance.cpp
Source/WebCore/bridge/objc/WebScriptObject.mm
Source/WebCore/contentextensions/ContentExtensionParser.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLPlugInImageElement.cpp
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm
Source/WebKit/mac/WebView/WebView.mm
Source/WebKit/win/ChangeLog
Source/WebKit/win/Plugins/PluginPackage.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Plugins/Netscape/NPJSObject.cpp

index c1ff708..e2190c8 100644 (file)
@@ -38,11 +38,13 @@ enum class ExceptionStatus {
 
 inline ExceptionStatus handleExceptionIfNeeded(JSC::ExecState* exec, JSValueRef* returnedExceptionRef)
 {
-    if (exec->hadException()) {
-        JSC::Exception* exception = exec->exception();
+    JSC::VM& vm = exec->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    if (UNLIKELY(scope.exception())) {
+        JSC::Exception* exception = scope.exception();
         if (returnedExceptionRef)
             *returnedExceptionRef = toRef(exec, exception->value());
-        exec->clearException();
+        scope.clearException();
 #if ENABLE(REMOTE_INSPECTOR)
         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception);
 #endif
index 453c68b..bf3619b 100644 (file)
@@ -631,6 +631,7 @@ set(JavaScriptCore_SOURCES
     runtime/BooleanObject.cpp
     runtime/BooleanPrototype.cpp
     runtime/CallData.cpp
+    runtime/CatchScope.cpp
     runtime/ClonedArguments.cpp
     runtime/CodeCache.cpp
     runtime/CodeSpecializationKind.cpp
@@ -660,8 +661,11 @@ set(JavaScriptCore_SOURCES
     runtime/ErrorInstance.cpp
     runtime/ErrorPrototype.cpp
     runtime/Exception.cpp
+    runtime/ExceptionEvent.cpp
+    runtime/ExceptionEventLocation.cpp
     runtime/ExceptionFuzz.cpp
     runtime/ExceptionHelpers.cpp
+    runtime/ExceptionScope.cpp
     runtime/Executable.cpp
     runtime/FunctionConstructor.cpp
     runtime/FunctionExecutableDump.cpp
index 1f66b93..3f3fbdc 100644 (file)
@@ -1,3 +1,751 @@
+2016-09-07  Mark Lam  <mark.lam@apple.com>
+
+        Add CatchScope and force all exception checks to be via ThrowScope or CatchScope.
+        https://bugs.webkit.org/show_bug.cgi?id=161498
+
+        Reviewed by Geoffrey Garen.
+
+        This patch refactors the ThrowScope class, and introduces a base ExceptionScope
+        that ThrowScope extends.  A CatchScope which extends the ExceptionScope is also
+        introduced.
+
+        ENABLE(THROW_SCOPE_VERIFICATION) is now renamed to ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+        which is a more suitable name now.
+
+        Note: exception scope verification is still disabled by default.  There are still
+        many places that need to be fixed up or re-expressed in a way that is friendly
+        to the verification.  I'll address those in subsequent patches.
+
+        After this patch, the code will statically enforce that:
+        1. all calls to throwException() go through a ThrowScope.
+        2. all calls to clearException() go through a CatchScope.
+        3. all exception checks go through an ExceptionScope in the form of a ThrowScope
+           or CatchScope.
+
+        A Summary of how to use ExceptionScopes
+        =======================================
+        1. If a function can throw a JS exception, it should declare a ThrowScope at the
+           top of the function (as early as possible).
+
+        2. If a function can clear JS exceptions, it should declare a CatchScope at the
+           top of the function (as early as possible).
+
+        Declaring a ThrowScope in a function means that the function may throw an exception
+        that its caller will have to handle.  Declaring a CatchScope in a function means
+        that the function intends to clear pending exceptions before returning to its
+        caller. 
+
+        For more details, see the notes below.
+        
+        Everything you may want to know about ExceptionScopes
+        =====================================================
+        ExceptionScope verification works to simulate exception throws and detect cases
+        where exception checks are missing.  The notes below will cover:
+
+            1. The VM::m_needExceptionCheck bit
+            2. ThrowScopes and CatchScopes
+            3. Verification of needed exception checks
+            3. Checking Exceptions
+            4. Simulating throws
+            5. Using ThrowScope::release()
+            6. Checking exceptions with ThrowScope::exception() / CatchScope::exception()
+            7. Checking exceptions by checking callee results
+            8. Debugging verification errors
+
+        1. The VM::m_needExceptionCheck bit
+
+           The VM has a m_needExceptionCheck bit that indicates when an exception may be
+           thrown.  You can think of the m_needExceptionCheck bit being set as a simulated
+           throw.
+
+        2. ThrowScopes and CatchScopes
+
+           Only ThrowScopes may throwException.  Only CatchScopes may catchException.
+
+           Every throw site must declare a ThrowScope instance using DECLARE_THROW_SCOPE
+           at the top of its function (as early as possible) e.g.
+                void foo(...)
+                {
+                    auto scope = DECLARE_THROW_SCOPE(vm);
+                    ...
+                    throwException(exec, scope, ...);
+                }
+
+           Note: by convention, every throw helper function must take a ThrowScope argument
+           instead of instantiating its own ThrowScope.  This allows the throw to be
+           attributed to the client code rather than the throw helper itself.
+
+           Every catch site (i.e. a site that calls clearException()) must declare a
+           CatchScope instance using DECLARE_CATCH_SCOPE at the top of its function.
+
+           If a function can both throw or clear exceptions, then the ThrowScope should
+           be declared first so that it can simulate a throw to the function's caller.
+
+           Note: ThrowScope and CatchScope both extend ExceptionScope so that ThrowScopes
+           can be aware if there's an enclosing CatchScope between it and the point where
+           C++ code returns to JS code.  This is needed to determine if the ThrowScope
+           should simulate a re-throw or not.  See (4) below for more details on returning
+           to JS code.
+
+        3. Verification of needed exception checks
+
+           a. On construction, each ThrowScope and CatchScope will verify that
+              VM::m_needExceptionCheck is not set.
+              This ensures that the caller of the current function has checked for exceptions
+              where needed before doing more work which lead to calling the current function.
+
+           b. On destruction, each ThrowScope and CatchScope will verify that
+              VM::m_needExceptionCheck is not set. This verification will be skipped if
+              the ThrowScope has been released (see (5) below).
+
+              This ensures that the function that owns this exception scope is not missing
+              any exception checks before returning.
+
+           c. When throwing an exception, the ThrowScope will verify that VM::m_needExceptionCheck
+              is not already set, unless it's been ask to rethrow the same Exception object.
+
+        4. Simulating throws
+
+           Throws are simulated by setting the m_needExceptionCheck bit.
+
+           The bit will only be set in the ThrowScope destructor except when the ThrowScope
+           detects the caller is a LLInt or JIT function.  LLInt or JIT functions will always
+           check for exceptions after a host C++ function returns to it.  However, they will
+           not clear the m_needExceptionCheck bit.
+
+           Hence, if the ThrowScope destructor detects the caller is a LLInt or JIT function,
+           it will just skip the setting of the bit.
+
+           Note: it is not needed nor correct to set the m_needExceptionCheck bit in the
+           throwException methods.  This is because, in practice, we always return
+           immediately after throwing an exception.  It doesn't make sense to set the bit in
+           the throw just to have to clear it immediately after before we do verification in
+           the ThrowScope destructor.
+
+        5. Using ThrowScope::release()
+
+           Calling release() means that the scope is released from its obligation to
+           verify the VM::m_needExceptionCheck bit on destruction.
+
+           release() should only be used at the bottom of a function if:
+
+           a. This function is going to let its caller check and handle the exception, e.g.
+
+                void foo(...)
+                {
+                    auto scope = DECLARE_THROW_SCOPE(vm);
+                    auto result = goo(); // may throw.
+
+                    ... // Code that will are not affected by a pending exceptions.
+
+                    scope.release(); // tell the ThrowScope that the caller will handle the exception.
+                    return result;
+                }
+
+           b. This function is going to do a tail call that may throw.
+
+                void foo(...)
+                {
+                    auto scope = DECLARE_THROW_SCOPE(vm);
+                    ...
+                    scope.release(); // tell the ThrowScope that the caller will handle the exception.
+                    return goo(); // may throw.
+                }
+
+              release() should not be used in code paths that branch. For example:
+
+                void foo(...)
+                {
+                    auto scope = DECLARE_THROW_SCOPE(vm);
+
+                    auto result = goo1(); // may throw.
+                    scope.release(); // WRONG !!! Don't do this.
+                    if (result)
+                        return;
+
+                    result = goo2(); // may throw.
+                    ...
+                    return result;
+                }
+
+            The above will result in a verification error in goo2()'s ThrowScope.  The
+            proper way to fix this verification is to do either (6) or (7) below.
+
+         6. Checking exceptions with ThrowScope::exception() / CatchScope::exception()
+
+            ThrowScope/CatchScope::exception() returns the thrown Exception object if
+            there is one pending.  Else, it returns nullptr.
+
+            It also clears the m_needExceptionCheck bit thereby indicating that we've
+            satisfied the needed exception check.  For example,
+
+                void foo(...)
+                {
+                    auto scope = DECLARE_THROW_SCOPE(vm);
+
+                    auto result = goo1(); // may throw.
+                    if (scope.exception())
+                        return;
+
+                    result = goo2(); // may throw.
+                    ...
+                    return result;
+                }
+
+            But sometimes, for optimization reasons, we may choose to test the result of
+            the callee function instead doing a load of the VM exception value.  See (7)
+            below.
+
+         7. Checking exceptions by checking callee results
+
+            This approach should only be applied when it makes a difference to performance.
+            If we need to do this, we should add an ASSERT() that invokes the scope's
+            exception() method to verify the result.  Since exception scope verification
+            is only done on DEBUG builds, this ASSERT will satisfy the verification
+            requirements without impacting performance.  For example,
+
+                void foo(...)
+                {
+                    auto scope = DECLARE_THROW_SCOPE(vm);
+
+                    bool failed = goo1(); // may throw.
+                    ASSERT(!!scope.exception() == failed)
+                    if (failed)
+                        return;
+
+                    result = goo2(); // may throw.
+                    ...
+                    return result;
+                }
+
+         8. Debugging verification errors
+
+            a. When verification fails, you will see a message followed by an assertion
+               failure.  For example:
+
+            ERROR: Unchecked JS exception:
+                This scope can throw a JS exception: setUpCall @ /Volumes/Data/ws6/OpenSource/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:1245
+                    (ExceptionScope::m_recursionDepth was ...)
+                But the exception was unchecked as of this scope: varargsSetup @ /Volumes/Data/ws6/OpenSource/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:1398
+                    (ExceptionScope::m_recursionDepth was ...)
+                [ backtrace here ]
+
+               The message tells you that failure was detected at in varargsSetup() at
+               LLIntSlowPaths.cpp line 1398, and that the missing exception check should
+               have happened somewhere between the call to setUpCall() at LLIntSlowPaths.cpp
+               line 1245 and it.
+
+               If that is insufficient information, you can ...
+
+            b. Dump simulated throws
+
+               Re-run the test case with JSC_dumpSimulatedThrows=true.  You will also see
+               back traces at each simulated throw.
+
+            c. Narrowing down the source of a simulated throw
+
+               Another technique for narrowing down the source of simulated throws is by
+               further dividing a function to smaller regions by separating each region
+               with additional local throw scopes.  For example,
+
+                ... // Region 1
+                { auto scope = DECLARE_THROW_SCOPE(vm); }
+                ... // Region 2
+                { auto scope = DECLARE_THROW_SCOPE(vm); }
+                ... // Region 3
+
+        * API/APIUtils.h:
+        (handleExceptionIfNeeded):
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bindings/ScriptFunctionCall.cpp:
+        (Deprecated::ScriptFunctionCall::call):
+        * bindings/ScriptValue.cpp:
+        (Deprecated::ScriptValue::toString):
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::pauseIfNeeded):
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::DebuggerCallFrame::evaluateWithScopeExtension):
+        * dfg/DFGOSRExitCompiler.cpp:
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::operationPutByValInternal):
+        * inspector/InjectedScriptManager.cpp:
+        (Inspector::InjectedScriptManager::createInjectedScript):
+        * inspector/JSGlobalObjectInspectorController.cpp:
+        (Inspector::JSGlobalObjectInspectorController::reportAPIException):
+        * inspector/JSInjectedScriptHost.cpp:
+        (Inspector::JSInjectedScriptHost::evaluateWithScopeExtension):
+        (Inspector::JSInjectedScriptHost::getInternalProperties):
+        (Inspector::JSInjectedScriptHost::weakMapEntries):
+        (Inspector::JSInjectedScriptHost::weakSetEntries):
+        (Inspector::JSInjectedScriptHost::iteratorEntries):
+        * inspector/JSJavaScriptCallFrame.cpp:
+        (Inspector::JSJavaScriptCallFrame::evaluateWithScopeExtension):
+        * inspector/ScriptCallStackFactory.cpp:
+        (Inspector::extractSourceInformationFromException):
+        * interpreter/CachedCall.h:
+        (JSC::CachedCall::CachedCall):
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::clearException): Deleted.
+        (JSC::ExecState::exception): Deleted.
+        (JSC::ExecState::hadException): Deleted.
+        (JSC::ExecState::lastException): Deleted.
+        (JSC::ExecState::clearLastException): Deleted.
+        * interpreter/Interpreter.cpp:
+        (JSC::eval):
+        (JSC::sizeOfVarargs):
+        (JSC::notifyDebuggerOfUnwinding):
+        (JSC::Interpreter::unwind):
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::prepareForRepeatCall):
+        (JSC::Interpreter::debug):
+        * interpreter/Interpreter.h:
+        (JSC::SuspendExceptionScope::SuspendExceptionScope):
+        * interpreter/ShadowChicken.cpp:
+        (JSC::ShadowChicken::functionsOnStack):
+        * jit/JITCode.cpp:
+        (JSC::JITCode::execute):
+        * jit/JITExceptions.cpp:
+        (JSC::genericUnwind):
+        * jit/JITOperations.cpp:
+        (JSC::getByVal):
+        * jsc.cpp:
+        (WTF::ImpureGetter::getOwnPropertySlot):
+        (GlobalObject::moduleLoaderResolve):
+        (GlobalObject::moduleLoaderFetch):
+        (functionCreateElement):
+        (functionRun):
+        (functionRunString):
+        (functionLoad):
+        (functionLoadString):
+        (functionReadFile):
+        (functionCheckSyntax):
+        (functionSetRandomSeed):
+        (functionLoadModule):
+        (functionCreateBuiltin):
+        (functionCheckModuleSyntax):
+        (functionGenerateHeapSnapshot):
+        (functionSamplingProfilerStackTraces):
+        (dumpException):
+        (checkUncaughtException):
+        (runWithScripts):
+        (runInteractive):
+        * llint/LLIntExceptions.cpp:
+        (JSC::LLInt::returnToThrow):
+        (JSC::LLInt::callToThrow):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * profiler/ProfilerBytecodeSequence.cpp:
+        (JSC::Profiler::BytecodeSequence::addSequenceProperties):
+        * profiler/ProfilerCompilation.cpp:
+        (JSC::Profiler::Compilation::toJS):
+        * profiler/ProfilerDatabase.cpp:
+        (JSC::Profiler::Database::toJS):
+        * profiler/ProfilerOSRExitSite.cpp:
+        (JSC::Profiler::OSRExitSite::toJS):
+        * profiler/ProfilerOriginStack.cpp:
+        (JSC::Profiler::OriginStack::toJS):
+        * runtime/ArrayPrototype.cpp:
+        (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::moveElements):
+        (JSC::concatAppendOne):
+        (JSC::arrayProtoPrivateFuncConcatMemcpy):
+        * runtime/BooleanConstructor.cpp:
+        (JSC::constructWithBooleanConstructor):
+        * runtime/CallData.cpp:
+        (JSC::call):
+        * runtime/CatchScope.cpp: Added.
+        (JSC::CatchScope::CatchScope):
+        (JSC::CatchScope::~CatchScope):
+        * runtime/CatchScope.h: Added.
+        (JSC::CatchScope::clearException):
+        (JSC::CatchScope::CatchScope):
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+        (JSC::CommonSlowPaths::opIn):
+        * runtime/CommonSlowPathsExceptions.cpp:
+        (JSC::CommonSlowPaths::interpreterThrowInCaller):
+        * runtime/Completion.cpp:
+        (JSC::evaluate):
+        (JSC::rejectPromise):
+        (JSC::loadAndEvaluateModule):
+        (JSC::loadModule):
+        * runtime/ConsoleObject.cpp:
+        (JSC::consoleProtoFuncAssert):
+        (JSC::consoleProtoFuncProfile):
+        (JSC::consoleProtoFuncProfileEnd):
+        (JSC::consoleProtoFuncTakeHeapSnapshot):
+        (JSC::consoleProtoFuncTime):
+        (JSC::consoleProtoFuncTimeEnd):
+        * runtime/DateConstructor.cpp:
+        (JSC::constructDate):
+        (JSC::dateParse):
+        * runtime/DatePrototype.cpp:
+        (JSC::dateProtoFuncToPrimitiveSymbol):
+        (JSC::dateProtoFuncToJSON):
+        * runtime/ErrorConstructor.cpp:
+        (JSC::Interpreter::constructWithErrorConstructor):
+        * runtime/ErrorInstance.cpp:
+        (JSC::ErrorInstance::sanitizedToString):
+        * runtime/ErrorPrototype.cpp:
+        (JSC::errorProtoFuncToString):
+        * runtime/ExceptionEventLocation.cpp: Added.
+        (WTF::printInternal):
+        * runtime/ExceptionEventLocation.h: Copied from Source/JavaScriptCore/runtime/ThrowScopeLocation.h.
+        (JSC::ExceptionEventLocation::ExceptionEventLocation):
+        (JSC::ThrowScopeLocation::ThrowScopeLocation): Deleted.
+        * runtime/ExceptionHelpers.h:
+        * runtime/ExceptionScope.cpp: Added.
+        (JSC::ExceptionScope::ExceptionScope):
+        (JSC::ExceptionScope::~ExceptionScope):
+        * runtime/ExceptionScope.h: Added.
+        (JSC::ExceptionScope::vm):
+        (JSC::ExceptionScope::recursionDepth):
+        (JSC::ExceptionScope::exception):
+        (JSC::ExceptionScope::ExceptionScope):
+        * runtime/FunctionConstructor.cpp:
+        (JSC::constructFunctionSkippingEvalEnabledCheck):
+        * runtime/FunctionPrototype.cpp:
+        (JSC::functionProtoFuncBind):
+        * runtime/GenericArgumentsInlines.h:
+        (JSC::GenericArguments<Type>::copyToArguments):
+        * runtime/GetterSetter.cpp:
+        (JSC::callGetter):
+        * runtime/InspectorInstrumentationObject.cpp:
+        (JSC::inspectorInstrumentationObjectLog):
+        * runtime/InternalFunction.cpp:
+        (JSC::InternalFunction::createSubclassStructure):
+        * runtime/IntlCollator.cpp:
+        (JSC::IntlCollator::initializeCollator):
+        (JSC::IntlCollator::createCollator):
+        (JSC::IntlCollator::resolvedOptions):
+        * runtime/IntlCollatorConstructor.cpp:
+        (JSC::constructIntlCollator):
+        (JSC::IntlCollatorConstructorFuncSupportedLocalesOf):
+        * runtime/IntlCollatorPrototype.cpp:
+        (JSC::IntlCollatorFuncCompare):
+        (JSC::IntlCollatorPrototypeGetterCompare):
+        * runtime/IntlDateTimeFormat.cpp:
+        (JSC::toDateTimeOptionsAnyDate):
+        (JSC::IntlDateTimeFormat::initializeDateTimeFormat):
+        (JSC::IntlDateTimeFormat::resolvedOptions):
+        (JSC::IntlDateTimeFormat::format):
+        * runtime/IntlDateTimeFormatConstructor.cpp:
+        (JSC::constructIntlDateTimeFormat):
+        (JSC::IntlDateTimeFormatConstructorFuncSupportedLocalesOf):
+        * runtime/IntlDateTimeFormatPrototype.cpp:
+        (JSC::IntlDateTimeFormatFuncFormatDateTime):
+        (JSC::IntlDateTimeFormatPrototypeGetterFormat):
+        * runtime/IntlNumberFormat.cpp:
+        (JSC::IntlNumberFormat::initializeNumberFormat):
+        (JSC::IntlNumberFormat::createNumberFormat):
+        (JSC::IntlNumberFormat::resolvedOptions):
+        * runtime/IntlNumberFormatConstructor.cpp:
+        (JSC::constructIntlNumberFormat):
+        (JSC::IntlNumberFormatConstructorFuncSupportedLocalesOf):
+        * runtime/IntlNumberFormatPrototype.cpp:
+        (JSC::IntlNumberFormatFuncFormatNumber):
+        (JSC::IntlNumberFormatPrototypeGetterFormat):
+        * runtime/IntlObject.cpp:
+        (JSC::intlBooleanOption):
+        (JSC::intlStringOption):
+        (JSC::intlNumberOption):
+        (JSC::canonicalizeLocaleList):
+        (JSC::supportedLocales):
+        * runtime/IntlObjectInlines.h:
+        (JSC::constructIntlInstanceWithWorkaroundForLegacyIntlConstructor):
+        * runtime/IteratorOperations.cpp:
+        (JSC::iteratorNext):
+        (JSC::iteratorStep):
+        (JSC::iteratorClose):
+        (JSC::iteratorForIterable):
+        * runtime/IteratorOperations.h:
+        (JSC::forEachInIterable):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::pop):
+        (JSC::JSArray::push):
+        (JSC::JSArray::copyToArguments):
+        * runtime/JSArrayBufferConstructor.cpp:
+        (JSC::constructArrayBuffer):
+        * runtime/JSArrayBufferPrototype.cpp:
+        (JSC::arrayBufferProtoFuncSlice):
+        * runtime/JSArrayInlines.h:
+        (JSC::getLength):
+        (JSC::toLength):
+        * runtime/JSBoundFunction.cpp:
+        (JSC::getBoundFunctionStructure):
+        (JSC::JSBoundFunction::create):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::putToPrimitive):
+        (JSC::JSValue::putToPrimitiveByIndex):
+        (JSC::JSValue::toStringSlowCase):
+        * runtime/JSCJSValueInlines.h:
+        (JSC::toPreferredPrimitiveType):
+        (JSC::JSValue::getPropertySlot):
+        (JSC::JSValue::equalSlowCaseInline):
+        * runtime/JSDataViewPrototype.cpp:
+        (JSC::getData):
+        (JSC::setData):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::setFunctionName):
+        * runtime/JSGenericTypedArrayView.h:
+        (JSC::JSGenericTypedArrayView::setIndex):
+        * runtime/JSGenericTypedArrayViewConstructorInlines.h:
+        (JSC::constructGenericTypedArrayViewFromIterator):
+        (JSC::constructGenericTypedArrayViewWithArguments):
+        (JSC::constructGenericTypedArrayView):
+        * runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
+        (JSC::speciesConstruct):
+        (JSC::genericTypedArrayViewProtoFuncCopyWithin):
+        (JSC::genericTypedArrayViewProtoFuncIncludes):
+        (JSC::genericTypedArrayViewProtoFuncIndexOf):
+        (JSC::genericTypedArrayViewProtoFuncJoin):
+        (JSC::genericTypedArrayViewProtoFuncLastIndexOf):
+        (JSC::genericTypedArrayViewProtoFuncSlice):
+        (JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
+        * runtime/JSGlobalObject.h:
+        (JSC::constructEmptyArray):
+        (JSC::constructArray):
+        (JSC::constructArrayNegativeIndexed):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncEval):
+        * runtime/JSJob.cpp:
+        (JSC::JSJobMicrotask::run):
+        * runtime/JSModuleEnvironment.cpp:
+        (JSC::JSModuleEnvironment::getOwnPropertySlot):
+        * runtime/JSModuleLoader.cpp:
+        (JSC::JSModuleLoader::fetch):
+        * runtime/JSModuleNamespaceObject.cpp:
+        (JSC::JSModuleNamespaceObject::finishCreation):
+        (JSC::JSModuleNamespaceObject::getOwnPropertySlot):
+        * runtime/JSModuleRecord.cpp:
+        (JSC::JSModuleRecord::instantiateDeclarations):
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::Stringifier):
+        (JSC::Stringifier::stringify):
+        (JSC::Stringifier::toJSON):
+        (JSC::Stringifier::appendStringifiedValue):
+        (JSC::Stringifier::Holder::appendNextProperty):
+        (JSC::Walker::walk):
+        (JSC::JSONProtoFuncParse):
+        * runtime/JSObject.cpp:
+        (JSC::ordinarySetSlow):
+        (JSC::JSObject::setPrototypeWithCycleCheck):
+        (JSC::callToPrimitiveFunction):
+        (JSC::JSObject::ordinaryToPrimitive):
+        (JSC::JSObject::defaultHasInstance):
+        (JSC::JSObject::getPropertyNames):
+        (JSC::JSObject::toNumber):
+        (JSC::JSObject::toString):
+        (JSC::JSObject::defineOwnNonIndexProperty):
+        (JSC::JSObject::getGenericPropertyNames):
+        (JSC::JSObject::getMethod):
+        * runtime/JSObjectInlines.h:
+        (JSC::createListFromArrayLike):
+        (JSC::JSObject::getPropertySlot):
+        (JSC::JSObject::getNonIndexPropertySlot):
+        * runtime/JSPromiseConstructor.cpp:
+        (JSC::constructPromise):
+        * runtime/JSPropertyNameEnumerator.h:
+        (JSC::propertyNameEnumerator):
+        * runtime/JSPropertyNameIterator.cpp:
+        (JSC::JSPropertyNameIterator::create):
+        * runtime/JSScope.cpp:
+        (JSC::isUnscopable):
+        (JSC::JSScope::resolve):
+        * runtime/JSString.cpp:
+        (JSC::JSString::equalSlowCase):
+        * runtime/JSStringJoiner.cpp:
+        (JSC::JSStringJoiner::join):
+        * runtime/LiteralParser.cpp:
+        (JSC::LiteralParser<CharType>::parse):
+        * runtime/MapConstructor.cpp:
+        (JSC::constructMap):
+        * runtime/MathObject.cpp:
+        (JSC::mathProtoFuncClz32):
+        (JSC::mathProtoFuncHypot):
+        (JSC::mathProtoFuncIMul):
+        * runtime/ModuleLoaderPrototype.cpp:
+        (JSC::moduleLoaderPrototypeParseModule):
+        (JSC::moduleLoaderPrototypeRequestedModules):
+        (JSC::moduleLoaderPrototypeModuleDeclarationInstantiation):
+        * runtime/NativeErrorConstructor.cpp:
+        (JSC::Interpreter::constructWithNativeErrorConstructor):
+        * runtime/NumberConstructor.cpp:
+        (JSC::constructWithNumberConstructor):
+        * runtime/ObjectConstructor.cpp:
+        (JSC::constructObject):
+        (JSC::objectConstructorGetPrototypeOf):
+        (JSC::objectConstructorSetPrototypeOf):
+        (JSC::objectConstructorGetOwnPropertyDescriptor):
+        (JSC::objectConstructorGetOwnPropertyDescriptors):
+        (JSC::objectConstructorGetOwnPropertyNames):
+        (JSC::objectConstructorGetOwnPropertySymbols):
+        (JSC::objectConstructorKeys):
+        (JSC::ownEnumerablePropertyKeys):
+        (JSC::toPropertyDescriptor):
+        (JSC::objectConstructorDefineProperty):
+        (JSC::defineProperties):
+        (JSC::objectConstructorSeal):
+        (JSC::objectConstructorFreeze):
+        (JSC::objectConstructorIsSealed):
+        (JSC::objectConstructorIsFrozen):
+        (JSC::objectConstructorIsExtensible):
+        (JSC::ownPropertyKeys):
+        * runtime/ObjectConstructor.h:
+        (JSC::constructObjectFromPropertyDescriptor):
+        * runtime/ObjectPrototype.cpp:
+        (JSC::objectProtoFuncHasOwnProperty):
+        (JSC::objectProtoFuncIsPrototypeOf):
+        (JSC::objectProtoFuncDefineGetter):
+        (JSC::objectProtoFuncDefineSetter):
+        (JSC::objectProtoFuncLookupGetter):
+        (JSC::objectProtoFuncLookupSetter):
+        (JSC::objectProtoFuncPropertyIsEnumerable):
+        (JSC::objectProtoFuncToLocaleString):
+        (JSC::objectProtoFuncToString):
+        * runtime/Operations.cpp:
+        (JSC::jsAddSlowCase):
+        * runtime/Options.h:
+        * runtime/PropertyDescriptor.cpp:
+        (JSC::PropertyDescriptor::slowGetterSetter):
+        * runtime/ProxyConstructor.cpp:
+        (JSC::makeRevocableProxy):
+        * runtime/ProxyObject.cpp:
+        (JSC::ProxyObject::toStringName):
+        (JSC::performProxyGet):
+        (JSC::ProxyObject::performGet):
+        (JSC::ProxyObject::performInternalMethodGetOwnProperty):
+        (JSC::ProxyObject::performHasProperty):
+        (JSC::ProxyObject::performPut):
+        (JSC::ProxyObject::putByIndexCommon):
+        (JSC::performProxyCall):
+        (JSC::performProxyConstruct):
+        (JSC::ProxyObject::performDelete):
+        (JSC::ProxyObject::performPreventExtensions):
+        (JSC::ProxyObject::performIsExtensible):
+        (JSC::ProxyObject::performDefineOwnProperty):
+        (JSC::ProxyObject::performGetOwnPropertyNames):
+        (JSC::ProxyObject::performSetPrototype):
+        (JSC::ProxyObject::performGetPrototype):
+        * runtime/ReflectObject.cpp:
+        (JSC::reflectObjectConstruct):
+        (JSC::reflectObjectDefineProperty):
+        (JSC::reflectObjectGet):
+        (JSC::reflectObjectGetOwnPropertyDescriptor):
+        (JSC::reflectObjectIsExtensible):
+        (JSC::reflectObjectPreventExtensions):
+        (JSC::reflectObjectSet):
+        (JSC::reflectObjectSetPrototypeOf):
+        * runtime/RegExpConstructor.cpp:
+        (JSC::toFlags):
+        (JSC::regExpCreate):
+        (JSC::constructRegExp):
+        * runtime/RegExpConstructor.h:
+        (JSC::isRegExp):
+        * runtime/RegExpObject.cpp:
+        (JSC::collectMatches):
+        (JSC::RegExpObject::matchGlobal):
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncCompile):
+        (JSC::flagsString):
+        (JSC::regExpProtoFuncToString):
+        (JSC::regExpProtoGetterFlags):
+        (JSC::regExpProtoFuncSearchFast):
+        (JSC::regExpProtoFuncSplitFast):
+        * runtime/SetConstructor.cpp:
+        (JSC::constructSet):
+        * runtime/StringConstructor.cpp:
+        (JSC::stringFromCodePoint):
+        (JSC::constructWithStringConstructor):
+        * runtime/StringObject.cpp:
+        (JSC::StringObject::defineOwnProperty):
+        * runtime/StringPrototype.cpp:
+        (JSC::replaceUsingRegExpSearch):
+        (JSC::operationStringProtoFuncReplaceRegExpEmptyStr):
+        (JSC::replaceUsingStringSearch):
+        (JSC::replace):
+        (JSC::stringProtoFuncReplaceUsingRegExp):
+        (JSC::stringProtoFuncReplaceUsingStringSearch):
+        (JSC::stringProtoFuncCodePointAt):
+        (JSC::stringProtoFuncSlice):
+        (JSC::stringProtoFuncSplitFast):
+        (JSC::stringProtoFuncSubstr):
+        (JSC::stringProtoFuncSubstring):
+        (JSC::stringProtoFuncLocaleCompare):
+        (JSC::toLocaleCase):
+        (JSC::stringProtoFuncBig):
+        (JSC::stringProtoFuncSmall):
+        (JSC::stringProtoFuncBlink):
+        (JSC::stringProtoFuncBold):
+        (JSC::stringProtoFuncFixed):
+        (JSC::stringProtoFuncItalics):
+        (JSC::stringProtoFuncStrike):
+        (JSC::stringProtoFuncSub):
+        (JSC::stringProtoFuncSup):
+        (JSC::stringProtoFuncFontcolor):
+        (JSC::stringProtoFuncFontsize):
+        (JSC::stringProtoFuncAnchor):
+        (JSC::stringProtoFuncLink):
+        (JSC::trimString):
+        (JSC::stringProtoFuncStartsWith):
+        (JSC::stringProtoFuncEndsWith):
+        (JSC::stringIncludesImpl):
+        (JSC::stringProtoFuncIncludes):
+        (JSC::builtinStringIncludesInternal):
+        (JSC::stringProtoFuncNormalize):
+        * runtime/SymbolConstructor.cpp:
+        (JSC::symbolConstructorFor):
+        * runtime/TemplateRegistry.cpp:
+        (JSC::TemplateRegistry::getTemplateObject):
+        * runtime/ThrowScope.cpp:
+        (JSC::ThrowScope::ThrowScope):
+        (JSC::ThrowScope::~ThrowScope):
+        (JSC::ThrowScope::throwException):
+        (JSC::ThrowScope::simulateThrow):
+        (JSC::ThrowScope::printIfNeedCheck): Deleted.
+        (JSC::ThrowScope::verifyExceptionCheckNeedIsSatisfied): Deleted.
+        * runtime/ThrowScope.h:
+        (JSC::ThrowScope::release):
+        (JSC::ThrowScope::ThrowScope):
+        (JSC::ThrowScope::throwException):
+        (JSC::ThrowScope::vm): Deleted.
+        (JSC::ThrowScope::exception): Deleted.
+        * runtime/ThrowScopeLocation.h: Removed.
+        * runtime/VM.cpp:
+        (JSC::VM::verifyExceptionCheckNeedIsSatisfied):
+        * runtime/VM.h:
+        (JSC::VM::exception):
+        (JSC::VM::clearException):
+        (JSC::VM::setException): Deleted.
+        * runtime/WeakMapConstructor.cpp:
+        (JSC::constructWeakMap):
+        * runtime/WeakSetConstructor.cpp:
+        (JSC::constructWeakSet):
+        * tools/JSDollarVMPrototype.cpp:
+        (JSC::functionPrint):
+
 2016-09-07  Andy VanWagoner  <thetalecrafter@gmail.com>
 
         [INTL] some valid language tags cause errors in Intl constructors
index b46d19c..87ffb6a 100644 (file)
                FE5068671AE25E280009DAB7 /* DeferredSourceDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5068661AE25E280009DAB7 /* DeferredSourceDump.cpp */; };
                FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */; };
                FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               FE6029D91D6E1E4F0030204D /* ThrowScopeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6029D81D6E1E330030204D /* ThrowScopeLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               FE6029D91D6E1E4F0030204D /* ExceptionEventLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6029D81D6E1E330030204D /* ExceptionEventLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               FE6491371D78F01D00A694D4 /* ExceptionScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6491361D78F01300A694D4 /* ExceptionScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               FE6491391D78F3AF00A694D4 /* ExceptionScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE6491381D78F3A300A694D4 /* ExceptionScope.cpp */; };
                FE68C6371B90DE040042BCB3 /* MacroAssemblerPrinter.h in Headers */ = {isa = PBXBuildFile; fileRef = FE68C6361B90DDD90042BCB3 /* MacroAssemblerPrinter.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FE68C6381B90DE0B0042BCB3 /* MacroAssemblerPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE68C6351B90DDD90042BCB3 /* MacroAssemblerPrinter.cpp */; };
                FE7BA60F1A1A7CEC00F1F7B4 /* HeapVerifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */; };
                FE7BA6101A1A7CEC00F1F7B4 /* HeapVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FE7C41961B97FC4B00F4D598 /* PingPongStackOverflowTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEDA50D41B97F442009A3B4F /* PingPongStackOverflowTest.cpp */; };
+               FE80C1971D775CDD008510C0 /* CatchScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE80C1961D775B27008510C0 /* CatchScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               FE80C1991D775FBE008510C0 /* CatchScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE80C1981D775FB4008510C0 /* CatchScope.cpp */; };
+               FE80C19B1D776A98008510C0 /* ExceptionEventLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE80C19A1D7768FD008510C0 /* ExceptionEventLocation.cpp */; };
                FE99B2491C24C3D300C82159 /* JITNegGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE99B2481C24B6D300C82159 /* JITNegGenerator.h */; };
                FE99B24A1C24C3D700C82159 /* JITNegGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE99B2471C24B6D300C82159 /* JITNegGenerator.cpp */; };
                FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861E182B7A0400F6D851 /* Breakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FE5068661AE25E280009DAB7 /* DeferredSourceDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeferredSourceDump.cpp; sourceTree = "<group>"; };
                FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMEntryScope.cpp; sourceTree = "<group>"; };
                FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMEntryScope.h; sourceTree = "<group>"; };
-               FE6029D81D6E1E330030204D /* ThrowScopeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThrowScopeLocation.h; sourceTree = "<group>"; };
+               FE6029D81D6E1E330030204D /* ExceptionEventLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionEventLocation.h; sourceTree = "<group>"; };
+               FE6491361D78F01300A694D4 /* ExceptionScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionScope.h; sourceTree = "<group>"; };
+               FE6491381D78F3A300A694D4 /* ExceptionScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExceptionScope.cpp; sourceTree = "<group>"; };
                FE68C6351B90DDD90042BCB3 /* MacroAssemblerPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MacroAssemblerPrinter.cpp; sourceTree = "<group>"; };
                FE68C6361B90DDD90042BCB3 /* MacroAssemblerPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerPrinter.h; sourceTree = "<group>"; };
                FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapVerifier.cpp; sourceTree = "<group>"; };
                FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapVerifier.h; sourceTree = "<group>"; };
+               FE80C1961D775B27008510C0 /* CatchScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CatchScope.h; sourceTree = "<group>"; };
+               FE80C1981D775FB4008510C0 /* CatchScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CatchScope.cpp; sourceTree = "<group>"; };
+               FE80C19A1D7768FD008510C0 /* ExceptionEventLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExceptionEventLocation.cpp; sourceTree = "<group>"; };
                FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInlines.h; sourceTree = "<group>"; };
                FE98B5B61BB9AE110073E7A6 /* JITSubGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITSubGenerator.h; sourceTree = "<group>"; };
                FE99B2471C24B6D300C82159 /* JITNegGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITNegGenerator.cpp; sourceTree = "<group>"; };
                                0FB7F38C15ED8E3800F167B2 /* ButterflyInlines.h */,
                                BCA62DFE0E2826230004F30D /* CallData.cpp */,
                                145C507F0D9DF63B0088F6B9 /* CallData.h */,
+                               FE80C1981D775FB4008510C0 /* CatchScope.cpp */,
+                               FE80C1961D775B27008510C0 /* CatchScope.h */,
                                BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */,
                                0FE0501C1AA9095600D33B33 /* ClonedArguments.cpp */,
                                0FE0501D1AA9095600D33B33 /* ClonedArguments.h */,
                                BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
                                FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
                                FE1C0FFC1B193E9800B53FCA /* Exception.h */,
+                               FE80C19A1D7768FD008510C0 /* ExceptionEventLocation.cpp */,
+                               FE6029D81D6E1E330030204D /* ExceptionEventLocation.h */,
                                0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
                                0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
                                1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
                                A72701B30DADE94900E548D7 /* ExceptionHelpers.h */,
+                               FE6491381D78F3A300A694D4 /* ExceptionScope.cpp */,
+                               FE6491361D78F01300A694D4 /* ExceptionScope.h */,
                                86CA032D1038E8440028A609 /* Executable.cpp */,
                                86CAFEE21035DDE60028A609 /* Executable.h */,
                                A7A8AF2917ADB5F3005AB174 /* Float32Array.h */,
                                0FA2C17A17D7CF84009D015F /* TestRunnerUtils.h */,
                                FE2E6A7A1D6EA5FE0060F896 /* ThrowScope.cpp */,
                                FE3422111D6B818C0032BE88 /* ThrowScope.h */,
-                               FE6029D81D6E1E330030204D /* ThrowScopeLocation.h */,
                                0F55989717C86C5600A1E543 /* ToNativeFromValue.h */,
                                0F2B66D817B6B5AB00A7AE3F /* TypedArrayAdaptors.h */,
                                0F2B66D917B6B5AB00A7AE3F /* TypedArrayController.cpp */,
                                FE3A06C01C11041A00390FDD /* JITRightShiftGenerator.h in Headers */,
                                708EBE241CE8F35800453146 /* IntlObjectInlines.h in Headers */,
                                0F070A481D543A90006E7232 /* CellContainerInlines.h in Headers */,
-                               FE6029D91D6E1E4F0030204D /* ThrowScopeLocation.h in Headers */,
+                               FE6029D91D6E1E4F0030204D /* ExceptionEventLocation.h in Headers */,
                                0FE0501B1AA9091100D33B33 /* GenericOffset.h in Headers */,
                                0F2B66E017B6B5AB00A7AE3F /* GenericTypedArrayView.h in Headers */,
                                0F2B66E117B6B5AB00A7AE3F /* GenericTypedArrayViewInlines.h in Headers */,
                                145722861437E140005FDE26 /* StrongInlines.h in Headers */,
                                BCDE3AB80E6C82F5001453A7 /* Structure.h in Headers */,
                                7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */,
+                               FE6491371D78F01D00A694D4 /* ExceptionScope.h in Headers */,
                                2AAAA31218BD49D100394CC8 /* StructureIDBlob.h in Headers */,
                                436E54531C468E7400B5AF73 /* B3LegalizeMemoryOffsets.h in Headers */,
                                2AF7382D18BBBF92008A5A37 /* StructureIDTable.h in Headers */,
                                709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
                                BC18C47A0E16F5CD00B34460 /* WebKitAvailability.h in Headers */,
                                A7DCB97312E5193F00911940 /* WriteBarrier.h in Headers */,
+                               FE80C1971D775CDD008510C0 /* CatchScope.h in Headers */,
                                2A4EC90C1860D6C20094F782 /* WriteBarrierBuffer.h in Headers */,
                                C2B6D75318A33793004A9301 /* WriteBarrierInlines.h in Headers */,
                                0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */,
                        buildActionMask = 2147483647;
                        files = (
                                0FFA549716B8835000B3A982 /* A64DOpcode.cpp in Sources */,
+                               FE6491391D78F3AF00A694D4 /* ExceptionScope.cpp in Sources */,
                                0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */,
                                0FEC856D1BDACDC70080FF74 /* AirAllocateStack.cpp in Sources */,
                                43422A661C16267500E2EB98 /* B3ReduceDoubleToFloat.cpp in Sources */,
                                0F2B66E617B6B5AB00A7AE3F /* JSArrayBufferPrototype.cpp in Sources */,
                                0F2B66E817B6B5AB00A7AE3F /* JSArrayBufferView.cpp in Sources */,
                                A5311C371C77CECA00E6B1B6 /* HeapSnapshotBuilder.cpp in Sources */,
+                               FE80C1991D775FBE008510C0 /* CatchScope.cpp in Sources */,
                                1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */,
                                86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */,
                                1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */,
                                0F4680A414BA7F8D00BFE272 /* LLIntSlowPaths.cpp in Sources */,
                                0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */,
                                14469DDE107EC7E700650446 /* Lookup.cpp in Sources */,
+                               FE80C19B1D776A98008510C0 /* ExceptionEventLocation.cpp in Sources */,
                                0F4680CC14BBB17A00BFE272 /* LowLevelInterpreter.cpp in Sources */,
                                A5AB49DC1BEC8082007020FB /* PerGlobalObjectWrapperWorld.cpp in Sources */,
                                14B723B212D7DA46003BD5ED /* MachineStackMarker.cpp in Sources */,
index c3d0d1b..b649c28 100644 (file)
@@ -105,10 +105,12 @@ JSValue ScriptFunctionCall::call(bool& hadException)
 {
     JSObject* thisObject = m_thisObject.jsObject();
 
-    JSLockHolder lock(m_exec);
+    VM& vm = m_exec->vm();
+    JSLockHolder lock(vm);
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue function = thisObject->get(m_exec, Identifier::fromString(m_exec, m_name));
-    if (m_exec->hadException()) {
+    if (UNLIKELY(scope.exception())) {
         hadException = true;
         return { };
     }
index 7f6ea16..02de112 100644 (file)
@@ -121,10 +121,13 @@ bool ScriptValue::getString(ExecState* scriptState, String& result) const
 
 String ScriptValue::toString(ExecState* scriptState) const
 {
+    VM& vm = scriptState->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
     String result = m_value.get().toString(scriptState)->value(scriptState);
     // Handle the case where an exception is thrown as part of invoking toString on the object.
-    if (scriptState->hadException())
-        scriptState->clearException();
+    if (UNLIKELY(scope.exception()))
+        scope.clearException();
     return result;
 }
 
index 5f849ec..577c6f2 100644 (file)
@@ -623,6 +623,9 @@ void Debugger::updateCallFrameAndPauseIfNeeded(CallFrame* callFrame)
 
 void Debugger::pauseIfNeeded(CallFrame* callFrame)
 {
+    VM& vm = callFrame->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     if (m_isPaused)
         return;
 
@@ -662,7 +665,7 @@ void Debugger::pauseIfNeeded(CallFrame* callFrame)
     {
         PauseReasonDeclaration reason(*this, didHitBreakpoint ? PausedForBreakpoint : m_reasonForPause);
         handlePause(vmEntryGlobalObject, m_reasonForPause);
-        RELEASE_ASSERT(!callFrame->hadException());
+        RELEASE_ASSERT(!scope.exception());
     }
 
     m_pausingBreakpointID = noBreakpointID;
index fb86368..db3c51d 100644 (file)
@@ -217,7 +217,9 @@ JSValue DebuggerCallFrame::evaluateWithScopeExtension(const String& script, JSOb
     if (!callFrame)
         return jsUndefined();
 
-    JSLockHolder lock(callFrame);
+    VM& vm = callFrame->vm();
+    JSLockHolder lock(vm);
+    auto catchScope = DECLARE_CATCH_SCOPE(vm);
 
     CodeBlock* codeBlock = nullptr;
     if (isTailDeleted())
@@ -228,7 +230,6 @@ JSValue DebuggerCallFrame::evaluateWithScopeExtension(const String& script, JSOb
         return jsUndefined();
     
     DebuggerEvalEnabler evalEnabler(callFrame);
-    VM& vm = callFrame->vm();
 
     EvalContextType evalContextType;
     
@@ -243,9 +244,9 @@ JSValue DebuggerCallFrame::evaluateWithScopeExtension(const String& script, JSOb
     JSScope::collectVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ);
 
     EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock->isStrictMode(), codeBlock->unlinkedCodeBlock()->derivedContextType(), codeBlock->unlinkedCodeBlock()->isArrowFunction(), evalContextType, &variablesUnderTDZ);
-    if (vm.exception()) {
-        exception = vm.exception();
-        vm.clearException();
+    if (UNLIKELY(catchScope.exception())) {
+        exception = catchScope.exception();
+        catchScope.clearException();
         return jsUndefined();
     }
 
@@ -257,9 +258,9 @@ JSValue DebuggerCallFrame::evaluateWithScopeExtension(const String& script, JSOb
 
     JSValue thisValue = this->thisValue();
     JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope());
-    if (vm.exception()) {
-        exception = vm.exception();
-        vm.clearException();
+    if (UNLIKELY(catchScope.exception())) {
+        exception = catchScope.exception();
+        catchScope.clearException();
     }
 
     if (scopeExtensionObject)
index be768ad..1fa3c0a 100644 (file)
@@ -112,14 +112,15 @@ extern "C" {
 
 void compileOSRExit(ExecState* exec)
 {
-    if (exec->vm().callFrameForCatch)
-        RELEASE_ASSERT(exec->vm().callFrameForCatch == exec);
+    VM* vm = &exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(*vm);
+
+    if (vm->callFrameForCatch)
+        RELEASE_ASSERT(vm->callFrameForCatch == exec);
     
     CodeBlock* codeBlock = exec->codeBlock();
     ASSERT(codeBlock);
     ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
-
-    VM* vm = &exec->vm();
     
     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
     // really be profitable.
@@ -131,7 +132,7 @@ void compileOSRExit(ExecState* exec)
     if (vm->callFrameForCatch)
         ASSERT(exit.m_kind == GenericUnwind);
     if (exit.isExceptionHandler())
-        ASSERT(!!vm->exception());
+        ASSERT_UNUSED(scope, !!scope.exception());
         
     
     prepareCodeOriginForOSRExit(exec, exit.m_codeOrigin);
index 0720705..624090c 100644 (file)
@@ -97,6 +97,7 @@ template<bool strict, bool direct>
 ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
 {
     VM* vm = &exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(*vm);
     NativeCallFrameTracer tracer(vm, exec);
 
     JSValue baseValue = JSValue::decode(encodedBase);
@@ -121,7 +122,7 @@ ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exe
 
     // Don't put to an object if toString throws an exception.
     auto propertyName = property.toPropertyKey(exec);
-    if (vm->exception())
+    if (UNLIKELY(scope.exception()))
         return;
 
     PutPropertySlot slot(baseValue, strict);
@@ -181,11 +182,12 @@ JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(vm);
     if (constructor->type() == JSFunctionType)
         return constructEmptyObject(exec, jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity)->objectAllocationProfile()->structure());
 
     JSValue proto = constructor->get(exec, exec->propertyNames().prototype);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
     if (proto.isObject())
         return constructEmptyObject(exec, asObject(proto));
@@ -209,12 +211,13 @@ EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValu
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     int32_t b = op2.toInt32(exec);
     return JSValue::encode(jsNumber(a & b));
@@ -224,12 +227,13 @@ EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     int32_t b = op2.toInt32(exec);
     return JSValue::encode(jsNumber(a | b));
@@ -239,12 +243,13 @@ EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValu
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     int32_t b = op2.toInt32(exec);
     return JSValue::encode(jsNumber(a ^ b));
@@ -254,12 +259,13 @@ EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSV
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     uint32_t b = op2.toUInt32(exec);
     return JSValue::encode(jsNumber(a << (b & 0x1f)));
@@ -269,12 +275,13 @@ EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSV
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     uint32_t b = op2.toUInt32(exec);
     return JSValue::encode(jsNumber(a >> (b & 0x1f)));
@@ -284,12 +291,13 @@ EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJS
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     uint32_t a = op1.toUInt32(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     uint32_t b = op2.toUInt32(exec);
     return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
@@ -315,12 +323,13 @@ EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue e
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
     return JSValue::encode(jsNumber(a / b));
@@ -330,10 +339,11 @@ double JIT_OPERATION operationArithAbs(ExecState* exec, EncodedJSValue encodedOp
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return PNaN;
     return fabs(a);
 }
@@ -342,10 +352,11 @@ int32_t JIT_OPERATION operationArithClz32(ExecState* exec, EncodedJSValue encode
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     uint32_t value = op1.toUInt32(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return 0;
     return clz32(value);
 }
@@ -354,10 +365,11 @@ double JIT_OPERATION operationArithCos(ExecState* exec, EncodedJSValue encodedOp
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     return cos(a);
 }
@@ -366,10 +378,11 @@ double JIT_OPERATION operationArithFRound(ExecState* exec, EncodedJSValue encode
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return PNaN;
     return static_cast<float>(a);
 }
@@ -378,10 +391,11 @@ double JIT_OPERATION operationArithLog(ExecState* exec, EncodedJSValue encodedOp
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return PNaN;
     return log(a);
 }
@@ -390,10 +404,11 @@ double JIT_OPERATION operationArithSin(ExecState* exec, EncodedJSValue encodedOp
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return PNaN;
     return sin(a);
 }
@@ -402,10 +417,11 @@ double JIT_OPERATION operationArithSqrt(ExecState* exec, EncodedJSValue encodedO
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     JSValue op1 = JSValue::decode(encodedOp1);
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm->exception()))
+    if (UNLIKELY(scope.exception()))
         return PNaN;
     return sqrt(a);
 }
@@ -431,7 +447,8 @@ EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue e
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
-    
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSValue baseValue = JSValue::decode(encodedBase);
     JSValue property = JSValue::decode(encodedProperty);
 
@@ -457,10 +474,10 @@ EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue e
     }
 
     baseValue.requireObjectCoercible(exec);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     auto propertyName = property.toPropertyKey(exec);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     return JSValue::encode(baseValue.get(exec, propertyName));
 }
@@ -469,7 +486,8 @@ EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
-    
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSValue property = JSValue::decode(encodedProperty);
 
     if (property.isUInt32())
@@ -490,7 +508,7 @@ EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base
     }
 
     auto propertyName = property.toPropertyKey(exec);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     return JSValue::encode(JSValue(base).get(exec, propertyName));
 }
@@ -859,6 +877,7 @@ EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJ
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue baseValue = JSValue::decode(encodedBase);
     JSValue thisVal = JSValue::decode(encodedThis);
@@ -884,11 +903,11 @@ EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJ
     }
 
     baseValue.requireObjectCoercible(exec);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
 
     auto property = subscript.toPropertyKey(exec);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     return JSValue::encode(baseValue.get(exec, property, slot));
 }
@@ -913,9 +932,10 @@ void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSVal
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return;
     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
 }
@@ -924,9 +944,10 @@ void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue enc
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return;
     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
 }
@@ -1441,9 +1462,9 @@ JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, Encode
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSString* str1 = JSValue::decode(a).toString(exec);
-    ASSERT(!vm.exception()); // Impossible, since we must have been given primitives.
+    ASSERT(!scope.exception()); // Impossible, since we must have been given primitives.
     JSString* str2 = JSValue::decode(b).toString(exec);
-    ASSERT(!vm.exception());
+    ASSERT(!scope.exception());
 
     if (sumOverflows<int32_t>(str1->length(), str2->length())) {
         throwOutOfMemoryError(exec, scope);
@@ -1460,11 +1481,11 @@ JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, Encode
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSString* str1 = JSValue::decode(a).toString(exec);
-    ASSERT(!vm.exception()); // Impossible, since we must have been given primitives.
+    ASSERT(!scope.exception()); // Impossible, since we must have been given primitives.
     JSString* str2 = JSValue::decode(b).toString(exec);
-    ASSERT(!vm.exception());
+    ASSERT(!scope.exception());
     JSString* str3 = JSValue::decode(c).toString(exec);
-    ASSERT(!vm.exception());
+    ASSERT(!scope.exception());
 
     if (sumOverflows<int32_t>(str1->length(), str2->length(), str3->length())) {
         throwOutOfMemoryError(exec, scope);
index 940cd0b..bbfe954 100644 (file)
@@ -134,7 +134,9 @@ String InjectedScriptManager::injectedScriptSource()
 
 JSC::JSObject* InjectedScriptManager::createInjectedScript(const String& source, ExecState* scriptState, int id)
 {
-    JSLockHolder lock(scriptState);
+    VM& vm = scriptState->vm();
+    JSLockHolder lock(vm);
+    auto scope = DECLARE_CATCH_SCOPE(vm);
 
     SourceCode sourceCode = makeSource(source);
     JSGlobalObject* globalObject = scriptState->lexicalGlobalObject();
@@ -157,7 +159,7 @@ JSC::JSObject* InjectedScriptManager::createInjectedScript(const String& source,
     args.append(jsNumber(id));
 
     JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args);
-    scriptState->clearException();
+    scope.clearException();
     return result.getObject();
 }
 
index ef543ed..16ddf55 100644 (file)
@@ -221,7 +221,9 @@ void JSGlobalObjectInspectorController::reportAPIException(ExecState* exec, Exce
     if (isTerminatedExecutionException(exception))
         return;
 
-    ErrorHandlingScope errorScope(exec->vm());
+    VM& vm = exec->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    ErrorHandlingScope errorScope(vm);
 
     RefPtr<ScriptCallStack> callStack = createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture);
     if (includesNativeCallStackWhenReportingExceptions())
@@ -230,7 +232,7 @@ void JSGlobalObjectInspectorController::reportAPIException(ExecState* exec, Exce
     // FIXME: <http://webkit.org/b/115087> Web Inspector: Should not evaluate JavaScript handling exceptions
     // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
     String errorMessage = exception->value().toString(exec)->value(exec);
-    exec->clearException();
+    scope.clearException();
 
     if (JSGlobalObjectConsoleClient::logToSystemConsole()) {
         if (callStack->size()) {
index ceb6ef3..c389c80 100644 (file)
@@ -103,7 +103,7 @@ JSValue JSInjectedScriptHost::evaluateWithScopeExtension(ExecState* exec)
         return throwTypeError(exec, scope, ASCIILiteral("InjectedScriptHost.evaluateWithScopeExtension first argument must be a string."));
 
     String program = scriptValue.toString(exec)->value(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
 
     NakedPtr<Exception> exception;
@@ -259,12 +259,13 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
         return jsUndefined();
 
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue value = exec->uncheckedArgument(0);
 
     if (JSPromise* promise = jsDynamicCast<JSPromise*>(value)) {
         unsigned index = 0;
         JSArray* array = constructEmptyArray(exec, nullptr);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         switch (promise->status(exec->vm())) {
         case JSPromise::Status::Pending:
@@ -286,7 +287,7 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
     if (JSBoundFunction* boundFunction = jsDynamicCast<JSBoundFunction*>(value)) {
         unsigned index = 0;
         JSArray* array = constructEmptyArray(exec, nullptr);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "targetFunction", boundFunction->targetFunction()));
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "boundThis", boundFunction->boundThis()));
@@ -298,7 +299,7 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
     if (ProxyObject* proxy = jsDynamicCast<ProxyObject*>(value)) {
         unsigned index = 0;
         JSArray* array = constructEmptyArray(exec, nullptr, 2);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("target"), proxy->target()));
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("handler"), proxy->handler()));
@@ -312,7 +313,7 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
 
             unsigned index = 0;
             JSArray* array = constructEmptyArray(exec, nullptr, 2);
-            if (UNLIKELY(vm.exception()))
+            if (UNLIKELY(scope.exception()))
                 return jsUndefined();
             array->putDirectIndex(exec, index++, constructInternalProperty(exec, "array", iteratedValue));
             array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", kind));
@@ -335,7 +336,7 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
         }
         unsigned index = 0;
         JSArray* array = constructEmptyArray(exec, nullptr, 2);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", mapIterator->iteratedValue()));
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
@@ -357,7 +358,7 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
         }
         unsigned index = 0;
         JSArray* array = constructEmptyArray(exec, nullptr, 2);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", setIterator->iteratedValue()));
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
@@ -367,7 +368,7 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
     if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(value)) {
         unsigned index = 0;
         JSArray* array = constructEmptyArray(exec, nullptr, 1);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "string", stringIterator->iteratedValue(exec)));
         return array;
@@ -376,7 +377,7 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
     if (JSPropertyNameIterator* propertyNameIterator = jsDynamicCast<JSPropertyNameIterator*>(value)) {
         unsigned index = 0;
         JSArray* array = constructEmptyArray(exec, nullptr, 1);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "object", propertyNameIterator->iteratedValue()));
         return array;
@@ -404,6 +405,7 @@ JSValue JSInjectedScriptHost::weakMapEntries(ExecState* exec)
         return jsUndefined();
 
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue value = exec->uncheckedArgument(0);
     JSWeakMap* weakMap = jsDynamicCast<JSWeakMap*>(value);
     if (!weakMap)
@@ -418,7 +420,7 @@ JSValue JSInjectedScriptHost::weakMapEntries(ExecState* exec)
         numberToFetch = static_cast<unsigned>(fetchDouble);
 
     JSArray* array = constructEmptyArray(exec, nullptr);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (auto it = weakMap->weakMapData()->begin(); it != weakMap->weakMapData()->end(); ++it) {
         JSObject* entry = constructEmptyObject(exec);
@@ -451,6 +453,7 @@ JSValue JSInjectedScriptHost::weakSetEntries(ExecState* exec)
         return jsUndefined();
 
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue value = exec->uncheckedArgument(0);
     JSWeakSet* weakSet = jsDynamicCast<JSWeakSet*>(value);
     if (!weakSet)
@@ -465,7 +468,7 @@ JSValue JSInjectedScriptHost::weakSetEntries(ExecState* exec)
         numberToFetch = static_cast<unsigned>(fetchDouble);
 
     JSArray* array = constructEmptyArray(exec, nullptr);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (auto it = weakSet->weakMapData()->begin(); it != weakSet->weakMapData()->end(); ++it) {
         JSObject* entry = constructEmptyObject(exec);
@@ -495,6 +498,7 @@ JSValue JSInjectedScriptHost::iteratorEntries(ExecState* exec)
         return jsUndefined();
 
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue iterator;
     JSValue value = exec->uncheckedArgument(0);
     if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(value))
@@ -505,7 +509,7 @@ JSValue JSInjectedScriptHost::iteratorEntries(ExecState* exec)
         iterator = stringIterator->clone(exec);
     else if (JSPropertyNameIterator* propertyNameIterator = jsDynamicCast<JSPropertyNameIterator*>(value)) {
         iterator = propertyNameIterator->clone(exec);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue();
     } else {
         if (JSObject* iteratorObject = jsDynamicCast<JSObject*>(value)) {
@@ -525,18 +529,18 @@ JSValue JSInjectedScriptHost::iteratorEntries(ExecState* exec)
         numberToFetch = static_cast<unsigned>(fetchDouble);
 
     JSArray* array = constructEmptyArray(exec, nullptr);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
 
     for (unsigned i = 0; i < numberToFetch; ++i) {
         JSValue next = iteratorStep(exec, iterator);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             break;
         if (next.isFalse())
             break;
 
         JSValue nextValue = iteratorValue(exec, next);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             break;
 
         JSObject* entry = constructEmptyObject(exec);
index 86fe9bb..3e668de 100644 (file)
@@ -83,7 +83,7 @@ JSValue JSJavaScriptCallFrame::evaluateWithScopeExtension(ExecState* exec)
         return throwTypeError(exec, scope, ASCIILiteral("JSJavaScriptCallFrame.evaluateWithScopeExtension first argument must be a string."));
 
     String script = scriptValue.toString(exec)->value(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
 
     NakedPtr<Exception> exception;
index 34d9ea5..8913527 100644 (file)
@@ -119,6 +119,9 @@ Ref<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState* exec, size_
 
 static void extractSourceInformationFromException(JSC::ExecState* exec, JSObject* exceptionObject, int* lineNumber, int* columnNumber, String* sourceURL)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
     // FIXME: <http://webkit.org/b/115087> Web Inspector: Should not need to evaluate JavaScript handling exceptions
     JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier::fromString(exec, "line"));
     *lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0;
@@ -126,7 +129,7 @@ static void extractSourceInformationFromException(JSC::ExecState* exec, JSObject
     *columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0;
     JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier::fromString(exec, "sourceURL"));
     *sourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined");
-    exec->clearException();
+    scope.clearException();
 }
 
 Ref<ScriptCallStack> createScriptCallStackFromException(JSC::ExecState* exec, JSC::Exception* exception, size_t maxStackSize)
index 471985a..7373d18 100644 (file)
@@ -54,7 +54,7 @@ namespace JSC {
                 m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, &m_protoCallFrame, function, argumentCount + 1, function->scope(), m_arguments.data());
             } else
                 throwStackOverflowError(callFrame, scope);
-            m_valid = !callFrame->hadException();
+            m_valid = !scope.exception();
         }
         
         JSValue call()
index e13ffbf..50d48c7 100644 (file)
@@ -116,14 +116,6 @@ namespace JSC  {
         // pointer, so these are inefficient, and should be used sparingly in new code.
         // But they're used in many places in legacy code, so they're not going away any time soon.
 
-        void clearException() { vm().clearException(); }
-
-        Exception* exception() const { return vm().exception(); }
-        bool hadException() const { return !!vm().exception(); }
-
-        Exception* lastException() const { return vm().lastException(); }
-        void clearLastException() { vm().clearLastException(); }
-
         AtomicStringTable* atomicStringTable() const { return vm().atomicStringTable(); }
         const CommonIdentifiers& propertyNames() const { return *vm().propertyNames; }
         const MarkedArgumentBuffer& emptyList() const { return *vm().emptyList; }
index 7394b92..c2bbdd5 100644 (file)
@@ -105,7 +105,7 @@ JSValue eval(CallFrame* callFrame)
         return jsUndefined();
     }
     String programSource = asString(program)->value(callFrame);
-    if (callFrame->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue();
     
     CallFrame* callerFrame = callFrame->callerFrame();
@@ -145,7 +145,7 @@ JSValue eval(CallFrame* callFrame)
         }
         
         // If the literal parser bailed, it should not have thrown exceptions.
-        ASSERT(!vm.exception());
+        ASSERT(!scope.exception());
 
         eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock->isStrictMode(), derivedContextType, evalContextType, isArrowFunctionContext, programSource, callerScopeChain);
 
@@ -188,7 +188,7 @@ unsigned sizeOfVarargs(CallFrame* callFrame, JSValue arguments, uint32_t firstVa
     default:
         RELEASE_ASSERT(arguments.isObject());
         length = getLength(callFrame, jsCast<JSObject*>(cell));
-        if (UNLIKELY(callFrame->hadException()))
+        if (UNLIKELY(scope.exception()))
             return 0;
         break;
     }
@@ -586,13 +586,15 @@ private:
 
 ALWAYS_INLINE static void notifyDebuggerOfUnwinding(CallFrame* callFrame)
 {
+    VM& vm = callFrame->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
     if (Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger()) {
-        SuspendExceptionScope scope(&callFrame->vm());
+        SuspendExceptionScope scope(&vm);
         if (jsDynamicCast<JSFunction*>(callFrame->callee()))
             debugger->returnEvent(callFrame);
         else
             debugger->didExecuteProgram(callFrame);
-        ASSERT(!callFrame->hadException());
+        ASSERT_UNUSED(throwScope, !throwScope.exception());
     }
 }
 
@@ -680,6 +682,8 @@ private:
 
 NEVER_INLINE HandlerInfo* Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exception* exception, UnwindStart unwindStart)
 {
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     if (unwindStart == UnwindFromCallerFrame) {
         if (callFrame->callerFrameOrVMEntryFrame() == vm.topVMEntryFrame)
             return nullptr;
@@ -698,7 +702,7 @@ NEVER_INLINE HandlerInfo* Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exc
     if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
         exceptionValue = jsNull();
 
-    ASSERT(vm.exception() && vm.exception()->stack().size());
+    ASSERT_UNUSED(scope, scope.exception() && scope.exception()->stack().size());
 
     // Calculate an exception handler vPC, unwinding call frames as necessary.
     HandlerInfo* handler = nullptr;
@@ -897,7 +901,7 @@ failedJSONP:
 
     // Execute the code:
     JSValue result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
-
+    throwScope.release();
     return checkedReturn(result);
 }
 
@@ -906,7 +910,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     VM& vm = callFrame->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
-    ASSERT(!callFrame->hadException());
+    ASSERT(!throwScope.exception());
     ASSERT(!vm.isCollectorBusy());
     if (vm.isCollectorBusy())
         return jsNull();
@@ -969,7 +973,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     VM& vm = callFrame->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
-    ASSERT(!callFrame->hadException());
+    ASSERT(!throwScope.exception());
     ASSERT(!vm.isCollectorBusy());
     // We throw in this case because we have to return something "valid" but we're
     // already in an invalid state.
@@ -1020,12 +1024,12 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
         else {
             result = JSValue::decode(vmEntryToNative(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
 
-            if (!callFrame->hadException())
+            if (LIKELY(!throwScope.exception()))
                 RELEASE_ASSERT(result.isObject());
         }
     }
 
-    if (callFrame->hadException())
+    if (UNLIKELY(throwScope.exception()))
         return 0;
     ASSERT(result.isObject());
     return checkedReturn(asObject(result));
@@ -1035,7 +1039,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE
 {
     VM& vm = *scope->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
-    ASSERT(!vm.exception());
+    ASSERT(!throwScope.exception());
     
     if (vm.isCollectorBusy())
         return CallFrameClosure();
@@ -1084,7 +1088,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     ASSERT(scope->vm() == &callFrame->vm());
-    ASSERT(!vm.exception());
+    ASSERT(!throwScope.exception());
     ASSERT(!vm.isCollectorBusy());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
     if (vm.isCollectorBusy())
@@ -1190,7 +1194,7 @@ JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* cal
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     ASSERT(scope->vm() == &callFrame->vm());
-    ASSERT(!vm.exception());
+    ASSERT(!throwScope.exception());
     ASSERT(!vm.isCollectorBusy());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
     if (vm.isCollectorBusy())
@@ -1231,12 +1235,14 @@ JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* cal
 
 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID)
 {
+    VM& vm = callFrame->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
     Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
     if (!debugger)
         return;
 
     ASSERT(callFrame->codeBlock()->hasDebuggerRequests());
-    ASSERT(!callFrame->hadException());
+    ASSERT_UNUSED(scope, !scope.exception());
 
     switch (debugHookID) {
         case DidEnterCallFrame:
@@ -1258,7 +1264,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook
             debugger->didReachBreakpoint(callFrame);
             break;
     }
-    ASSERT(!callFrame->hadException());
-}    
+    ASSERT(!scope.exception());
+}
 
 } // namespace JSC
index 89331e9..646271a 100644 (file)
@@ -31,6 +31,7 @@
 #define Interpreter_h
 
 #include "ArgList.h"
+#include "CatchScope.h"
 #include "JSCJSValue.h"
 #include "JSCell.h"
 #include "JSObject.h"
@@ -38,6 +39,7 @@
 #include "SourceProvider.h"
 #include "StackAlignment.h"
 #include "StackFrame.h"
+#include "ThrowScope.h"
 #include <wtf/HashMap.h>
 #include <wtf/text/StringBuilder.h>
 
@@ -92,8 +94,9 @@ namespace JSC {
         SuspendExceptionScope(VM* vm)
             : m_vm(vm)
         {
-            oldException = vm->exception();
-            vm->clearException();
+            auto scope = DECLARE_CATCH_SCOPE(*vm);
+            oldException = scope.exception();
+            scope.clearException();
         }
         ~SuspendExceptionScope()
         {
index c598351..fd81029 100644 (file)
@@ -436,8 +436,9 @@ void ShadowChicken::dump(PrintStream& out) const
 JSArray* ShadowChicken::functionsOnStack(ExecState* exec)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSArray* result = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return nullptr;
 
     iterate(
index 26b69c5..9c92552 100644 (file)
@@ -69,6 +69,7 @@ void JITCode::validateReferences(const TrackedReferences&)
 
 JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame)
 {
+    auto scope = DECLARE_THROW_SCOPE(*vm);
     void* entryAddress;
     JSFunction* function = jsDynamicCast<JSFunction*>(protoCallFrame->callee());
 
@@ -78,7 +79,7 @@ JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame)
     } else
         entryAddress = addressForCall(MustCheckArity).executableAddress();
     JSValue result = JSValue::decode(vmEntryToJavaScript(entryAddress, vm, protoCallFrame));
-    return vm->exception() ? jsNull() : result;
+    return scope.exception() ? jsNull() : result;
 }
 
 DFG::CommonData* JITCode::dfgCommon()
index fd6364e..e12b309 100644 (file)
@@ -42,6 +42,7 @@ namespace JSC {
 
 void genericUnwind(VM* vm, ExecState* callFrame, UnwindStart unwindStart)
 {
+    auto scope = DECLARE_THROW_SCOPE(*vm);
     if (Options::breakOnThrow()) {
         CodeBlock* codeBlock = callFrame->codeBlock();
         if (codeBlock)
@@ -58,7 +59,7 @@ void genericUnwind(VM* vm, ExecState* callFrame, UnwindStart unwindStart)
     }
     vm->shadowChicken().log(*vm, shadowChickenTopFrame, ShadowChicken::Packet::throwPacket());
     
-    Exception* exception = vm->exception();
+    Exception* exception = scope.exception();
     RELEASE_ASSERT(exception);
     HandlerInfo* handler = vm->interpreter->unwind(*vm, callFrame, exception, unwindStart); // This may update callFrame.
 
index 4ddd111..0a429b2 100644 (file)
@@ -275,7 +275,7 @@ EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubI
     LOG_IC((ICEvent::OperationInOptimize, base->classInfo(), ident));
     PropertySlot slot(base, PropertySlot::InternalMethodType::HasProperty);
     bool result = asObject(base)->getPropertySlot(exec, ident, slot);
-    if (vm->exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     
     RELEASE_ASSERT(accessType == stubInfo->accessType);
@@ -489,6 +489,7 @@ ALWAYS_INLINE static bool isStringOrSymbol(JSValue value)
 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value, ByValInfo* byValInfo)
 {
     VM& vm = callFrame->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     if (LIKELY(subscript.isUInt32())) {
         byValInfo->tookSlowPath = true;
         uint32_t i = subscript.asUInt32();
@@ -510,7 +511,7 @@ static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript,
 
     auto property = subscript.toPropertyKey(callFrame);
     // Don't put to an object if toString threw an exception.
-    if (callFrame->vm().exception())
+    if (UNLIKELY(scope.exception()))
         return;
 
     if (byValInfo->stubInfo && (!isStringOrSymbol(subscript) || byValInfo->cachedId != property))
@@ -522,6 +523,8 @@ static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript,
 
 static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ByValInfo* byValInfo)
 {
+    VM& vm = callFrame->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     bool isStrictMode = callFrame->codeBlock()->isStrictMode();
     if (LIKELY(subscript.isUInt32())) {
         // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
@@ -553,7 +556,7 @@ static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue s
 
     // Don't put to an object if toString threw an exception.
     auto property = subscript.toPropertyKey(callFrame);
-    if (callFrame->vm().exception())
+    if (UNLIKELY(scope.exception()))
         return;
 
     if (Optional<uint32_t> index = parseIndex(property)) {
@@ -774,16 +777,16 @@ void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValu
 
 EncodedJSValue JIT_OPERATION operationCallEval(ExecState* exec, ExecState* execCallee)
 {
-    UNUSED_PARAM(exec);
+    VM* vm = &exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(*vm);
 
     execCallee->setCodeBlock(0);
     
     if (!isHostFunction(execCallee->calleeAsValue(), globalFuncEval))
         return JSValue::encode(JSValue());
 
-    VM* vm = &execCallee->vm();
     JSValue result = eval(execCallee);
-    if (vm->exception())
+    if (UNLIKELY(scope.exception()))
         return EncodedJSValue();
     
     return JSValue::encode(result);
@@ -807,7 +810,7 @@ static SlowPathReturnType handleHostCall(ExecState* execCallee, JSValue callee,
             NativeCallFrameTracer tracer(vm, execCallee);
             execCallee->setCallee(asObject(callee));
             vm->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
-            if (vm->exception()) {
+            if (UNLIKELY(scope.exception())) {
                 return encodeResult(
                     vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
                     reinterpret_cast<void*>(KeepTheFrame));
@@ -836,7 +839,7 @@ static SlowPathReturnType handleHostCall(ExecState* execCallee, JSValue callee,
         NativeCallFrameTracer tracer(vm, execCallee);
         execCallee->setCallee(asObject(callee));
         vm->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
-        if (vm->exception()) {
+        if (UNLIKELY(scope.exception())) {
             return encodeResult(
                 vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
                 reinterpret_cast<void*>(KeepTheFrame));
@@ -1462,8 +1465,10 @@ enum class AccessorType {
 
 static void putAccessorByVal(ExecState* exec, JSObject* base, JSValue subscript, int32_t attribute, JSObject* accessor, AccessorType accessorType)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     auto propertyKey = subscript.toPropertyKey(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return;
 
     if (accessorType == AccessorType::Getter)
@@ -1608,8 +1613,10 @@ static bool canAccessArgumentIndexQuickly(JSObject& object, uint32_t index)
 
 static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     if (LIKELY(baseValue.isCell() && subscript.isString())) {
-        VM& vm = exec->vm();
         Structure& structure = *baseValue.asCell()->structure(vm);
         if (JSCell::canUseFastGetOwnProperty(structure)) {
             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
@@ -1651,10 +1658,10 @@ static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, B
     }
 
     baseValue.requireObjectCoercible(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     auto property = subscript.toPropertyKey(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
 
     ASSERT(exec->bytecodeOffset());
@@ -1845,6 +1852,7 @@ EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSV
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue baseValue = JSValue::decode(encodedBase);
     JSValue subscript = JSValue::decode(encodedSubscript);
     
@@ -1862,10 +1870,10 @@ EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSV
         }
     } else {
         baseValue.requireObjectCoercible(exec);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         auto property = subscript.toPropertyKey(exec);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         result = baseValue.get(exec, property);
     }
@@ -1914,10 +1922,10 @@ size_t JIT_OPERATION operationDeleteByVal(ExecState* exec, EncodedJSValue encode
     if (key.getUInt32(index))
         couldDelete = baseObj->methodTable(vm)->deletePropertyByIndex(baseObj, exec, index);
     else {
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return false;
         Identifier property = key.toPropertyKey(exec);
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return false;
         couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, property);
     }
@@ -2122,7 +2130,7 @@ void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC)
     PutPropertySlot slot(scope, codeBlock->isStrictMode(), PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
     scope->methodTable()->put(scope, exec, ident, value, slot);
     
-    if (vm.exception())
+    if (UNLIKELY(throwScope.exception()))
         return;
 
     CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, getPutInfo, slot, ident);
@@ -2371,11 +2379,12 @@ EncodedJSValue JIT_OPERATION operationValueAddNoOptimize(ExecState* exec, Encode
 
 ALWAYS_INLINE static EncodedJSValue unprofiledMul(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
     return JSValue::encode(jsNumber(a * b));
@@ -2383,6 +2392,7 @@ ALWAYS_INLINE static EncodedJSValue unprofiledMul(VM& vm, ExecState* exec, Encod
 
 ALWAYS_INLINE static EncodedJSValue profiledMul(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
 {
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
@@ -2390,10 +2400,10 @@ ALWAYS_INLINE static EncodedJSValue profiledMul(VM& vm, ExecState* exec, Encoded
         arithProfile->observeLHSAndRHS(op1, op2);
 
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     
     JSValue result = jsNumber(a * b);
@@ -2468,11 +2478,12 @@ EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(ExecState* exec
 
 ALWAYS_INLINE static EncodedJSValue unprofiledSub(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
     return JSValue::encode(jsNumber(a - b));
@@ -2480,6 +2491,7 @@ ALWAYS_INLINE static EncodedJSValue unprofiledSub(VM& vm, ExecState* exec, Encod
 
 ALWAYS_INLINE static EncodedJSValue profiledSub(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
 {
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
@@ -2487,10 +2499,10 @@ ALWAYS_INLINE static EncodedJSValue profiledSub(VM& vm, ExecState* exec, Encoded
         arithProfile->observeLHSAndRHS(op1, op2);
 
     double a = op1.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     
     JSValue result = jsNumber(a - b);
@@ -2580,13 +2592,14 @@ int32_t JIT_OPERATION operationCheckIfExceptionIsUncatchableAndNotifyProfiler(Ex
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
-    RELEASE_ASSERT(!!vm.exception());
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    RELEASE_ASSERT(!!scope.exception());
 
-    if (isTerminatedExecutionException(vm.exception())) {
+    if (isTerminatedExecutionException(scope.exception())) {
         genericUnwind(&vm, exec);
         return 1;
-    } else
-        return 0;
+    }
+    return 0;
 }
 
 } // extern "C"
index 236cfd3..fa1bcb5 100644 (file)
@@ -301,12 +301,14 @@ public:
 
     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
     {
+        VM& vm = exec->vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
         ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
         
         if (thisObject->m_delegate) {
             if (thisObject->m_delegate->getPropertySlot(exec, name, slot))
                 return true;
-            if (exec->hadException())
+            if (UNLIKELY(scope.exception()))
                 return false;
         }
 
@@ -1037,11 +1039,14 @@ static String resolvePath(const DirectoryName& directoryName, const ModuleName&
 
 JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
 {
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     const Identifier key = keyValue.toPropertyKey(exec);
-    if (exec->hadException()) {
-        JSValue exception = exec->exception();
-        exec->clearException();
+    if (UNLIKELY(scope.exception())) {
+        JSValue exception = scope.exception();
+        scope.clearException();
         return deferred->reject(exec, exception);
     }
 
@@ -1054,9 +1059,9 @@ JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObjec
             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
     } else {
         const Identifier referrer = referrerValue.toPropertyKey(exec);
-        if (exec->hadException()) {
-            JSValue exception = exec->exception();
-            exec->clearException();
+        if (UNLIKELY(scope.exception())) {
+            JSValue exception = scope.exception();
+            scope.clearException();
             return deferred->reject(exec, exception);
         }
         if (referrer.isSymbol()) {
@@ -1142,11 +1147,13 @@ static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>&
 
 JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue)
 {
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     String moduleKey = key.toWTFString(exec);
-    if (exec->hadException()) {
-        JSValue exception = exec->exception();
-        exec->clearException();
+    if (UNLIKELY(scope.exception())) {
+        JSValue exception = scope.exception();
+        scope.clearException();
         return deferred->reject(exec, exception);
     }
 
@@ -1257,9 +1264,9 @@ EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
 {
     VM& vm = exec->vm();
+    JSLockHolder lock(vm);
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    JSLockHolder lock(exec);
     Root* root = jsDynamicCast<Root*>(exec->argument(0));
     if (!root)
         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Cannot create Element without a Root."))));
@@ -1447,7 +1454,7 @@ EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     String fileName = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     Vector<char> script;
     if (!fetchScriptFromLocalFileSystem(fileName, script))
@@ -1481,7 +1488,7 @@ EncodedJSValue JSC_HOST_CALL functionRunString(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     String source = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
@@ -1509,7 +1516,7 @@ EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     String fileName = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     Vector<char> script;
     if (!fetchScriptFromLocalFileSystem(fileName, script))
@@ -1530,7 +1537,7 @@ EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     String sourceCode = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
 
@@ -1547,7 +1554,7 @@ EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     String fileName = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
@@ -1562,7 +1569,7 @@ EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     String fileName = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     Vector<char> script;
     if (!fetchScriptFromLocalFileSystem(fileName, script))
@@ -1622,8 +1629,11 @@ EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     unsigned seed = exec->argument(0).toUInt32(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     exec->lexicalGlobalObject()->weakRandom().setSeed(seed);
     return JSValue::encode(jsUndefined());
@@ -1876,14 +1886,14 @@ EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     String fileName = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     Vector<char> script;
     if (!fetchScriptFromLocalFileSystem(fileName, script))
         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
 
     JSInternalPromise* promise = loadAndEvaluateModule(exec, fileName);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     JSValue error;
@@ -1901,14 +1911,16 @@ EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     if (exec->argumentCount() < 1 || !exec->argument(0).isString())
         return JSValue::encode(jsUndefined());
 
     String functionText = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
 
-    VM& vm = exec->vm();
     const SourceCode& source = makeSource(functionText);
     JSFunction* func = JSFunction::createBuiltinFunction(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
 
@@ -1927,7 +1939,7 @@ EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     String source = exec->argument(0).toWTFString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     StopWatch stopWatch;
@@ -1953,14 +1965,16 @@ EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*
 
 EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
 {
-    JSLockHolder lock(exec);
+    VM& vm = exec->vm();
+    JSLockHolder lock(vm);
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     HeapSnapshotBuilder snapshotBuilder(exec->vm().ensureHeapProfiler());
     snapshotBuilder.buildSnapshot();
 
     String jsonString = snapshotBuilder.json();
     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
-    RELEASE_ASSERT(!exec->hadException());
+    RELEASE_ASSERT(!scope.exception());
     return result;
 }
 
@@ -1998,7 +2012,7 @@ EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec
 
     String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
-    RELEASE_ASSERT(!exec->hadException());
+    RELEASE_ASSERT(!scope.exception());
     return result;
 }
 #endif // ENABLE(SAMPLING_PROFILER)
@@ -2101,6 +2115,16 @@ int main(int argc, char** argv)
 
 static void dumpException(GlobalObject* globalObject, JSValue exception)
 {
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
+#define CHECK_EXCEPTION() do { \
+        if (scope.exception()) { \
+            scope.clearException(); \
+            return; \
+        } \
+    } while (false)
+
     printf("Exception: %s\n", exception.toWTFString(globalObject->globalExec()).utf8().data());
 
     Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
@@ -2109,9 +2133,13 @@ static void dumpException(GlobalObject* globalObject, JSValue exception)
     Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
     
     JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
+    CHECK_EXCEPTION();
     JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
+    CHECK_EXCEPTION();
     JSValue lineNumberValue = exception.get(globalObject->globalExec(), lineNumberID);
+    CHECK_EXCEPTION();
     JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
+    CHECK_EXCEPTION();
     
     if (nameValue.toWTFString(globalObject->globalExec()) == "SyntaxError"
         && (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
@@ -2123,11 +2151,14 @@ static void dumpException(GlobalObject* globalObject, JSValue exception)
     
     if (!stackValue.isUndefinedOrNull())
         printf("%s\n", stackValue.toWTFString(globalObject->globalExec()).utf8().data());
+
+#undef CHECK_EXCEPTION
 }
 
 static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue exception, const String& expectedExceptionName, bool alwaysDumpException)
 {
-    vm.clearException();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    scope.clearException();
     if (!exception) {
         printf("Expected uncaught exception with name '%s' but none was thrown\n", expectedExceptionName.utf8().data());
         return false;
@@ -2135,13 +2166,13 @@ static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue e
 
     ExecState* exec = globalObject->globalExec();
     JSValue exceptionClass = globalObject->get(exec, Identifier::fromString(exec, expectedExceptionName));
-    if (!exceptionClass.isObject() || vm.exception()) {
+    if (!exceptionClass.isObject() || scope.exception()) {
         printf("Expected uncaught exception with name '%s' but given exception class is not defined\n", expectedExceptionName.utf8().data());
         return false;
     }
 
     bool isInstanceOfExpectedException = jsCast<JSObject*>(exceptionClass)->hasInstance(exec, exception);
-    if (vm.exception()) {
+    if (scope.exception()) {
         printf("Expected uncaught exception with name '%s' but given exception class fails performing hasInstance\n", expectedExceptionName.utf8().data());
         return false;
     }
@@ -2165,6 +2196,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
         JSC::Options::dumpGeneratedBytecodes() = true;
 
     VM& vm = globalObject->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
     bool success = true;
 
     auto checkException = [&] (bool isLastFile, bool hasException, JSValue value) {
@@ -2207,7 +2239,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
         if (isModule) {
             if (!promise)
                 promise = loadAndEvaluateModule(globalObject->globalExec(), jscSource(scriptBuffer, fileName));
-            vm.clearException();
+            scope.clearException();
 
             JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
                 checkException(isLastFile, false, exec->argument(0));
@@ -2224,13 +2256,14 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
         } else {
             NakedPtr<Exception> evaluationException;
             JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, fileName), JSValue(), evaluationException);
+            ASSERT(!scope.exception());
             if (evaluationException)
                 returnValue = evaluationException->value();
             checkException(isLastFile, evaluationException, returnValue);
         }
 
         scriptBuffer.clear();
-        vm.clearException();
+        scope.clearException();
     }
 
 #if ENABLE(REGEXP_TRACING)
@@ -2243,6 +2276,9 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
 
 static void runInteractive(GlobalObject* globalObject)
 {
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
     String interpreterName(ASCIILiteral("Interpreter"));
     
     bool shouldQuit = false;
@@ -2293,7 +2329,7 @@ static void runInteractive(GlobalObject* globalObject)
         else
             printf("%s\n", returnValue.toWTFString(globalObject->globalExec()).utf8().data());
 
-        globalObject->globalExec()->clearException();
+        scope.clearException();
         globalObject->vm().drainMicrotasks();
     }
     printf("\n");
index 0450d56..f8abd3a 100644 (file)
@@ -46,7 +46,8 @@ Instruction* returnToThrow(ExecState* exec)
     UNUSED_PARAM(exec);
 #if LLINT_SLOW_PATH_TRACING
     VM* vm = &exec->vm();
-    dataLog("Throwing exception ", vm->exception(), " (returnToThrow).\n");
+    auto scope = DECLARE_THROW_SCOPE(*vm);
+    dataLog("Throwing exception ", scope.exception(), " (returnToThrow).\n");
 #endif
     return LLInt::exceptionInstructions();
 }
@@ -56,7 +57,8 @@ void* callToThrow(ExecState* exec)
     UNUSED_PARAM(exec);
 #if LLINT_SLOW_PATH_TRACING
     VM* vm = &exec->vm();
-    dataLog("Throwing exception ", vm->exception(), " (callToThrow).\n");
+    auto scope = DECLARE_THROW_SCOPE(*vm);
+    dataLog("Throwing exception ", scope.exception(), " (callToThrow).\n");
 #endif
     return LLInt::getCodePtr(llint_throw_during_call_trampoline);
 }
index fb722cc..9a00a14 100644 (file)
@@ -882,7 +882,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_val_direct)
 
     // Don't put to an object if toString threw an exception.
     auto property = subscript.toPropertyKey(exec);
-    if (exec->vm().exception())
+    if (throwScope.exception())
         LLINT_END();
 
     if (Optional<uint32_t> index = parseIndex(property))
index 07545ba..0dac4db 100644 (file)
@@ -79,15 +79,16 @@ const Bytecode& BytecodeSequence::forBytecodeIndex(unsigned bytecodeIndex) const
 void BytecodeSequence::addSequenceProperties(ExecState* exec, JSObject* result) const
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSArray* header = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return;
     for (unsigned i = 0; i < m_header.size(); ++i)
         header->putDirectIndex(exec, i, jsString(exec, String::fromUTF8(m_header[i])));
     result->putDirect(vm, exec->propertyNames().header, header);
     
     JSArray* sequence = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return;
     for (unsigned i = 0; i < m_sequence.size(); ++i)
         sequence->putDirectIndex(exec, i, m_sequence[i].toJS(exec));
index 0218e56..3b37d14 100644 (file)
@@ -115,28 +115,29 @@ void Compilation::dump(PrintStream& out) const
 JSValue Compilation::toJS(ExecState* exec) const
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSObject* result = constructEmptyObject(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     result->putDirect(vm, exec->propertyNames().bytecodesID, jsNumber(m_bytecodes->id()));
     result->putDirect(vm, exec->propertyNames().compilationKind, jsString(exec, String::fromUTF8(toCString(m_kind))));
     
     JSArray* profiledBytecodes = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < m_profiledBytecodes.size(); ++i)
         profiledBytecodes->putDirectIndex(exec, i, m_profiledBytecodes[i].toJS(exec));
     result->putDirect(vm, exec->propertyNames().profiledBytecodes, profiledBytecodes);
     
     JSArray* descriptions = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < m_descriptions.size(); ++i)
         descriptions->putDirectIndex(exec, i, m_descriptions[i].toJS(exec));
     result->putDirect(vm, exec->propertyNames().descriptions, descriptions);
     
     JSArray* counters = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (auto it = m_counters.begin(), end = m_counters.end(); it != end; ++it) {
         JSObject* counterEntry = constructEmptyObject(exec);
@@ -147,14 +148,14 @@ JSValue Compilation::toJS(ExecState* exec) const
     result->putDirect(vm, exec->propertyNames().counters, counters);
     
     JSArray* exitSites = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < m_osrExitSites.size(); ++i)
         exitSites->putDirectIndex(exec, i, m_osrExitSites[i].toJS(exec));
     result->putDirect(vm, exec->propertyNames().osrExitSites, exitSites);
     
     JSArray* exits = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < m_osrExits.size(); ++i)
         exits->putDirectIndex(exec, i, m_osrExits[i].toJS(exec));
index 559a58b..f994eb2 100644 (file)
@@ -100,24 +100,25 @@ void Database::addCompilation(CodeBlock* codeBlock, PassRefPtr<Compilation> pass
 JSValue Database::toJS(ExecState* exec) const
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSObject* result = constructEmptyObject(exec);
     
     JSArray* bytecodes = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < m_bytecodes.size(); ++i)
         bytecodes->putDirectIndex(exec, i, m_bytecodes[i].toJS(exec));
     result->putDirect(vm, exec->propertyNames().bytecodes, bytecodes);
     
     JSArray* compilations = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < m_compilations.size(); ++i)
         compilations->putDirectIndex(exec, i, m_compilations[i]->toJS(exec));
     result->putDirect(vm, exec->propertyNames().compilations, compilations);
     
     JSArray* events = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < m_events.size(); ++i)
         events->putDirectIndex(exec, i, m_events[i].toJS(exec));
index 04687d7..ab74591 100644 (file)
@@ -37,8 +37,9 @@ namespace JSC { namespace Profiler {
 JSValue OSRExitSite::toJS(ExecState* exec) const
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSArray* result = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < m_codeAddresses.size(); ++i)
         result->putDirectIndex(exec, i, jsString(exec, toString(RawPointer(m_codeAddresses[i]))));
index 2298acf..351a6db 100644 (file)
@@ -101,8 +101,9 @@ void OriginStack::dump(PrintStream& out) const
 JSValue OriginStack::toJS(ExecState* exec) const
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSArray* result = constructEmptyArray(exec, 0);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     
     for (unsigned i = 0; i < m_stack.size(); ++i)
index 3d36d3a..3ae9a84 100644 (file)
@@ -196,6 +196,9 @@ enum class SpeciesConstructResult {
 
 static ALWAYS_INLINE std::pair<SpeciesConstructResult, JSObject*> speciesConstructArray(ExecState* exec, JSObject* thisObject, unsigned length)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // ECMA 9.4.2.3: https://tc39.github.io/ecma262/#sec-arrayspeciescreate
     JSValue constructor = jsUndefined();
     if (LIKELY(isArray(exec, thisObject))) {
@@ -205,7 +208,7 @@ static ALWAYS_INLINE std::pair<SpeciesConstructResult, JSObject*> speciesConstru
             return std::make_pair(SpeciesConstructResult::FastPath, nullptr);
 
         constructor = thisObject->get(exec, exec->propertyNames().constructor);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return std::make_pair(SpeciesConstructResult::Exception, nullptr);
         if (constructor.isConstructor()) {
             JSObject* constructorObject = jsCast<JSObject*>(constructor);
@@ -214,12 +217,12 @@ static ALWAYS_INLINE std::pair<SpeciesConstructResult, JSObject*> speciesConstru
         }
         if (constructor.isObject()) {
             constructor = constructor.get(exec, exec->propertyNames().speciesSymbol);
-            if (exec->hadException())
+            if (UNLIKELY(scope.exception()))
                 return std::make_pair(SpeciesConstructResult::Exception, nullptr);
             if (constructor.isNull())
                 return std::make_pair(SpeciesConstructResult::FastPath, nullptr);;
         }
-    } else if (exec->hadException())
+    } else if (UNLIKELY(scope.exception()))
         return std::make_pair(SpeciesConstructResult::Exception, nullptr);
 
     if (constructor.isUndefined())
@@ -228,7 +231,7 @@ static ALWAYS_INLINE std::pair<SpeciesConstructResult, JSObject*> speciesConstru
     MarkedArgumentBuffer args;
     args.append(jsNumber(length));
     JSObject* newObject = construct(exec, constructor, args, "Species construction did not get a valid constructor");
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return std::make_pair(SpeciesConstructResult::Exception, nullptr);
     return std::make_pair(SpeciesConstructResult::CreatedObject, newObject);
 }
@@ -284,10 +287,10 @@ void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned current
         unsigned from = k + currentCount;
         unsigned to = k + resultCount;
         if (JSValue value = getProperty(exec, thisObj, from)) {
-            if (exec->hadException())
+            if (UNLIKELY(scope.exception()))
                 return;
             thisObj->putByIndexInline(exec, to, value, true);
-            if (exec->hadException())
+            if (UNLIKELY(scope.exception()))
                 return;
         } else if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to)) {
             throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
@@ -330,31 +333,32 @@ void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned curre
         unsigned from = k + currentCount - 1;
         unsigned to = k + resultCount - 1;
         if (JSValue value = getProperty(exec, thisObj, from)) {
-            if (exec->hadException())
+            if (UNLIKELY(scope.exception()))
                 return;
             thisObj->putByIndexInline(exec, to, value, true);
         } else if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to)) {
             throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
             return;
         }
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return;
     }
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
 
     // 1. Let array be the result of calling ToObject on the this value.
     JSObject* thisObject = thisValue.toObject(exec);
-    VM& vm = exec->vm();
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     
     // 2. Let func be the result of calling the [[Get]] internal method of array with argument "join".
     JSValue function = JSValue(thisObject).get(exec, exec->propertyNames().join);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     // 3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
@@ -383,18 +387,18 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
         return JSValue::encode(earlyReturnValue);
 
     JSStringJoiner joiner(*exec, ',', length);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     for (unsigned i = 0; i < length; ++i) {
         JSValue element = thisArray->tryGetIndexQuickly(i);
         if (!element) {
             element = thisArray->get(exec, i);
-            if (UNLIKELY(vm.exception()))
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(jsUndefined());
         }
         joiner.append(*exec, element);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 
@@ -403,14 +407,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
 
     JSObject* thisObject = thisValue.toObject(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     unsigned length = getLength(exec, thisObject);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     StringRecursionChecker checker(exec, thisObject);
@@ -418,52 +424,52 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
         return JSValue::encode(earlyReturnValue);
 
     JSStringJoiner stringJoiner(*exec, ',', length);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
 #if ENABLE(INTL)
     ArgList arguments(exec);
     for (unsigned i = 0; i < length; ++i) {
         JSValue element = thisObject->getIndex(exec, i);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         if (element.isUndefinedOrNull())
             element = jsEmptyString(exec);
         else {
             JSValue conversionFunction = element.get(exec, exec->propertyNames().toLocaleString);
-            if (exec->hadException())
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(jsUndefined());
             CallData callData;
             CallType callType = getCallData(conversionFunction, callData);
             if (callType != CallType::None) {
                 element = call(exec, conversionFunction, callType, callData, element, arguments);
-                if (exec->hadException())
+                if (UNLIKELY(scope.exception()))
                 return JSValue::encode(jsUndefined());
             }
         }
         stringJoiner.append(*exec, element);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 #else // !ENABLE(INTL)
     for (unsigned i = 0; i < length; ++i) {
         JSValue element = thisObject->getIndex(exec, i);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         if (element.isUndefinedOrNull())
             continue;
         JSValue conversionFunction = element.get(exec, exec->propertyNames().toLocaleString);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         CallData callData;
         CallType callType = getCallData(conversionFunction, callData);
         if (callType != CallType::None) {
             element = call(exec, conversionFunction, callType, callData, element, exec->emptyList());
-            if (exec->hadException())
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(jsUndefined());
         }
         stringJoiner.append(*exec, element);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 #endif // !ENABLE(INTL)
@@ -498,15 +504,16 @@ static inline bool holesMustForwardToPrototype(ExecState& state, JSObject* objec
 
 static JSValue slowJoin(ExecState& exec, JSObject* thisObject, JSString* separator, uint64_t length)
 {
+    VM& vm = exec.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // 5. If len is zero, return the empty String.
     if (!length)
         return jsEmptyString(&exec);
 
-    VM& vm = exec.vm();
-
     // 6. Let element0 be Get(O, "0").
     JSValue element0 = thisObject->getIndex(&exec, 0);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue();
 
     // 7. If element0 is undefined or null, let R be the empty String; otherwise, let R be ? ToString(element0).
@@ -515,7 +522,7 @@ static JSValue slowJoin(ExecState& exec, JSObject* thisObject, JSString* separat
         r = jsEmptyString(&exec);
     else
         r = element0.toString(&exec);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue();
 
     // 8. Let k be 1.
@@ -524,7 +531,7 @@ static JSValue slowJoin(ExecState& exec, JSObject* thisObject, JSString* separat
     for (uint64_t k = 1; k < length; ++k) {
         // b. Let element be ? Get(O, ! ToString(k)).
         JSValue element = thisObject->get(&exec, Identifier::fromString(&exec, AtomicString::number(k)));
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return JSValue();
 
         // c. If element is undefined or null, let next be the empty String; otherwise, let next be ? ToString(element).
@@ -535,7 +542,7 @@ static JSValue slowJoin(ExecState& exec, JSObject* thisObject, JSString* separat
             next = jsEmptyString(&exec);
         } else
             next = element.toString(&exec);
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return JSValue();
 
         // a. Let S be the String value produced by concatenating R and sep.
@@ -561,6 +568,9 @@ static inline bool canUseFastJoin(const JSObject* thisObject)
 
 static inline JSValue fastJoin(ExecState& state, JSObject* thisObject, StringView separator, unsigned length)
 {
+    VM& vm = state.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     switch (thisObject->indexingType()) {
     case ALL_CONTIGUOUS_INDEXING_TYPES:
     case ALL_INT32_INDEXING_TYPES: {
@@ -568,7 +578,7 @@ static inline JSValue fastJoin(ExecState& state, JSObject* thisObject, StringVie
         if (length > butterfly.publicLength())
             break;
         JSStringJoiner joiner(state, separator, length);
-        if (state.hadException())
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         auto data = butterfly.contiguous().data();
         bool holesKnownToBeOK = false;
@@ -592,7 +602,7 @@ static inline JSValue fastJoin(ExecState& state, JSObject* thisObject, StringVie
         if (length > butterfly.publicLength())
             break;
         JSStringJoiner joiner(state, separator, length);
-        if (state.hadException())
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         auto data = butterfly.contiguousDouble().data();
         bool holesKnownToBeOK = false;
@@ -602,7 +612,7 @@ static inline JSValue fastJoin(ExecState& state, JSObject* thisObject, StringVie
                 joiner.append(state, jsDoubleNumber(value));
             else {
                 if (!holesKnownToBeOK) {
-                    if (thisObject->structure(state.vm())->holesMustForwardToPrototype(state.vm()))
+                    if (thisObject->structure(vm)->holesMustForwardToPrototype(vm))
                         goto generalCase;
                     holesKnownToBeOK = true;
                 }
@@ -615,14 +625,14 @@ static inline JSValue fastJoin(ExecState& state, JSObject* thisObject, StringVie
 
 generalCase:
     JSStringJoiner joiner(state, separator, length);
-    if (state.hadException())
+    if (UNLIKELY(scope.exception()))
         return jsUndefined();
     for (unsigned i = 0; i < length; ++i) {
         JSValue element = thisObject->getIndex(&state, i);
-        if (state.hadException())
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
         joiner.append(state, element);
-        if (state.hadException())
+        if (UNLIKELY(scope.exception()))
             return jsUndefined();
     }
     return joiner.join(state);
@@ -630,6 +640,9 @@ generalCase:
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // 1. Let O be ? ToObject(this value).
     JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
     if (!thisObject)
@@ -641,7 +654,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
 
     // 2. Let len be ? ToLength(? Get(O, "length")).
     double length = toLength(exec, thisObject);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
 
     // 3. If separator is undefined, let separator be the single-element String ",".
@@ -653,7 +666,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
             uint64_t length64 = static_cast<uint64_t>(length);
             ASSERT(static_cast<double>(length64) == length);
             JSString* jsSeparator = jsSingleCharacterString(exec, comma);
-            if (exec->hadException())
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(JSValue());
 
             return JSValue::encode(slowJoin(*exec, thisObject, jsSeparator, length64));
@@ -666,7 +679,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
 
     // 4. Let sep be ? ToString(separator).
     JSString* jsSeparator = separatorValue.toString(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     if (UNLIKELY(length > std::numeric_limits<unsigned>::max() || !canUseFastJoin(thisObject))) {
@@ -692,7 +705,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
     if (!thisObj)
         return JSValue::encode(JSValue());
     unsigned length = getLength(exec, thisObj);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     JSValue result;
@@ -701,7 +714,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
         result = jsUndefined();
     } else {
         result = thisObj->get(exec, length - 1);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, length - 1)) {
             throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
@@ -714,6 +727,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
 
     if (isJSArray(thisValue) && exec->argumentCount() == 1) {
@@ -726,7 +741,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
     if (!thisObj)
         return JSValue::encode(JSValue());
     unsigned length = getLength(exec, thisObj);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     for (unsigned n = 0; n < exec->argumentCount(); n++) {
@@ -738,7 +753,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
             Identifier propertyName = Identifier::fromString(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toWTFString(exec));
             thisObj->methodTable()->put(thisObj, exec, propertyName, exec->uncheckedArgument(n), slot);
         }
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
     
@@ -757,7 +772,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
         return JSValue::encode(JSValue());
 
     unsigned length = getLength(exec, thisObject);
-    if (vm.exception())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     switch (thisObject->indexingType()) {
@@ -798,41 +813,41 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
     for (unsigned lower = 0; lower < middle; lower++) {
         unsigned upper = length - lower - 1;
         bool lowerExists = thisObject->hasProperty(exec, lower);
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         JSValue lowerValue;
         if (lowerExists) {
             lowerValue = thisObject->get(exec, lower);
-            if (UNLIKELY(vm.exception()))
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(jsUndefined());
         }
 
         bool upperExists = thisObject->hasProperty(exec, upper);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         JSValue upperValue;
         if (upperExists) {
             upperValue = thisObject->get(exec, upper);
-            if (UNLIKELY(vm.exception()))
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(jsUndefined());
         }
 
         if (upperExists) {
             thisObject->putByIndexInline(exec, lower, upperValue, true);
-            if (vm.exception())
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(JSValue());
         } else if (!thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, lower)) {
-            if (!vm.exception())
+            if (!scope.exception())
                 throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
             return JSValue::encode(JSValue());
         }
 
         if (lowerExists) {
             thisObject->putByIndexInline(exec, upper, lowerValue, true);
-            if (vm.exception())
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(JSValue());
         } else if (!thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, upper)) {
-            if (!vm.exception())
+            if (!scope.exception())
                 throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
             return JSValue::encode(JSValue());
         }
@@ -842,11 +857,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
     if (!thisObj)
         return JSValue::encode(JSValue());
     unsigned length = getLength(exec, thisObj);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     JSValue result;
@@ -856,7 +873,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
     } else {
         result = thisObj->getIndex(exec, 0);
         shift<JSArray::ShiftCountForShift>(exec, thisObj, 0, 1, 0, length);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         putLength(exec, thisObj, jsNumber(length - 1));
     }
@@ -867,11 +884,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
 {
     // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
     if (!thisObj)
         return JSValue::encode(JSValue());
     unsigned length = getLength(exec, thisObj);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
@@ -892,14 +910,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
         result = speciesResult.second;
     else {
         result = constructEmptyArray(exec, nullptr, end - begin);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 
     unsigned n = 0;
     for (unsigned k = begin; k < end; k++, n++) {
         JSValue v = getProperty(exec, thisObj, k);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         if (v)
             result->putDirectIndex(exec, n, v);
@@ -919,7 +937,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
     if (!thisObj)
         return JSValue::encode(JSValue());
     unsigned length = getLength(exec, thisObj);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     if (!exec->argumentCount()) {
@@ -932,7 +950,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
             result = speciesResult.second;
         else {
             result = constructEmptyArray(exec, nullptr);
-            if (UNLIKELY(vm.exception()))
+            if (UNLIKELY(scope.exception()))
                 return JSValue::encode(jsUndefined());
         }
 
@@ -967,12 +985,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
             
             for (unsigned k = 0; k < deleteCount; ++k) {
                 JSValue v = getProperty(exec, thisObj, k + begin);
-                if (UNLIKELY(vm.exception()))
+                if (UNLIKELY(scope.exception()))
                     return JSValue::encode(jsUndefined());
                 if (UNLIKELY(!v))
                     continue;
                 result->putByIndexInline(exec, k, v, true);
-                if (UNLIKELY(vm.exception()))
+                if (UNLIKELY(scope.exception()))
                     return JSValue::encode(jsUndefined());
             }
         } else {
@@ -982,7 +1000,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
             
             for (unsigned k = 0; k < deleteCount; ++k) {
                 JSValue v = getProperty(exec, thisObj, k + begin);
-                if (UNLIKELY(vm.exception()))
+                if (UNLIKELY(scope.exception()))
                     return JSValue::encode(jsUndefined());
                 if (UNLIKELY(!v))
                     continue;
@@ -994,16 +1012,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
     unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);
     if (additionalArgs < deleteCount) {
         shift<JSArray::ShiftCountForSplice>(exec, thisObj, begin, deleteCount, additionalArgs, length);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     } else if (additionalArgs > deleteCount) {
         unshift<JSArray::ShiftCountForSplice>(exec, thisObj, begin, deleteCount, additionalArgs, length);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
     for (unsigned k = 0; k < additionalArgs; ++k) {
         thisObj->putByIndexInline(exec, k + begin, exec->uncheckedArgument(k + 2), true);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
     
@@ -1013,24 +1031,26 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     // 15.4.4.13
 
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
     if (!thisObj)
         return JSValue::encode(JSValue());
     unsigned length = getLength(exec, thisObj);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     unsigned nrArgs = exec->argumentCount();
     if (nrArgs) {
         unshift<JSArray::ShiftCountForShift>(exec, thisObj, 0, 0, nrArgs, length);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
     for (unsigned k = 0; k < nrArgs; ++k) {
         thisObj->putByIndexInline(exec, k, exec->uncheckedArgument(k), true);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
     JSValue result = jsNumber(length + nrArgs);
@@ -1040,26 +1060,28 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // 15.4.4.14
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
     if (!thisObj)
         return JSValue::encode(JSValue());
-    VM& vm = exec->vm();
     unsigned length = getLength(exec, thisObj);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
     JSValue searchElement = exec->argument(0);
     for (; index < length; ++index) {
         JSValue e = getProperty(exec, thisObj, index);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         if (!e)
             continue;
         if (JSValue::strictEqual(exec, searchElement, e))
             return JSValue::encode(jsNumber(index));
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 
@@ -1068,6 +1090,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // 15.4.4.15
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
     if (!thisObj)
@@ -1089,18 +1114,17 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
             index = static_cast<unsigned>(fromDouble);
     }
 
-    VM& vm = exec->vm();
     JSValue searchElement = exec->argument(0);
     do {
         RELEASE_ASSERT(index < length);
         JSValue e = getProperty(exec, thisObj, index);
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
         if (!e)
             continue;
         if (JSValue::strictEqual(exec, searchElement, e))
             return JSValue::encode(jsNumber(index));
-        if (UNLIKELY(vm.exception()))
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     } while (index--);
 
@@ -1109,23 +1133,25 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
 
 static bool moveElements(ExecState* exec, VM& vm, JSArray* target, unsigned targetOffset, JSArray* source, unsigned sourceLength)
 {
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     if (LIKELY(!hasAnyArrayStorage(source->indexingType()) && !source->structure()->holesMustForwardToPrototype(vm))) {
         for (unsigned i = 0; i < sourceLength; ++i) {
             JSValue value = source->tryGetIndexQuickly(i);
             if (value) {
                 target->putDirectIndex(exec, targetOffset + i, value);
-                if (vm.exception())
+                if (UNLIKELY(scope.exception()))
                     return false;
             }
         }
     } else {
         for (unsigned i = 0; i < sourceLength; ++i) {
             JSValue value = getProperty(exec, source, i);
-            if (vm.exception())
+            if (UNLIKELY(scope.exception()))
                 return false;
             if (value) {
                 target->putDirectIndex(exec, targetOffset + i, value);
-                if (vm.exception())
+                if (UNLIKELY(scope.exception()))
                     return false;
             }
         }
@@ -1154,7 +1180,7 @@ static EncodedJSValue concatAppendOne(ExecState* exec, VM& vm, JSArray* first, J
 
     if (!result->appendMemcpy(exec, vm, 0, first)) {
         if (!moveElements(exec, vm, result, 0, first, firstArraySize)) {
-            ASSERT(vm.exception());
+            ASSERT(scope.exception());
             return JSValue::encode(JSValue());
         }
     }
@@ -1199,12 +1225,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncConcatMemcpy(ExecState* exec)
     IndexingType type = firstArray->mergeIndexingTypeForCopying(secondType);
     if (type == NonArray || !firstArray->canFastCopy(vm, secondArray) || firstArraySize + secondArraySize >= MIN_SPARSE_ARRAY_INDEX) {
         JSArray* result = constructEmptyArray(exec, nullptr, firstArraySize + secondArraySize);
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(JSValue());
 
         if (!moveElements(exec, vm, result, 0, firstArray, firstArraySize)
             || !moveElements(exec, vm, result, firstArraySize, secondArray, secondArraySize)) {
-            ASSERT(vm.exception());
+            ASSERT(scope.exception());
             return JSValue::encode(JSValue());
         }
 
index b3215e7..77ea77a 100644 (file)
@@ -48,12 +48,14 @@ void BooleanConstructor::finishCreation(VM& vm, BooleanPrototype* booleanPrototy
 // ECMA 15.6.2
 static EncodedJSValue JSC_HOST_CALL constructWithBooleanConstructor(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue boolean = jsBoolean(exec->argument(0).toBoolean(exec));
     Structure* booleanStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure());
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
-    BooleanObject* obj = BooleanObject::create(exec->vm(), booleanStructure);
-    obj->setInternalValue(exec->vm(), boolean);
+    BooleanObject* obj = BooleanObject::create(vm, booleanStructure);
+    obj->setInternalValue(vm, boolean);
     return JSValue::encode(obj);
 }
 
index 6d0f812..a758923 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -42,10 +42,12 @@ JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const C
 
 JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args, NakedPtr<Exception>& returnedException)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
     JSValue result = call(exec, functionObject, callType, callData, thisValue, args);
-    if (exec->hadException()) {
-        returnedException = exec->exception();
-        exec->clearException();
+    if (UNLIKELY(scope.exception())) {
+        returnedException = scope.exception();
+        scope.clearException();
         return jsUndefined();
     }
     RELEASE_ASSERT(result);
diff --git a/Source/JavaScriptCore/runtime/CatchScope.cpp b/Source/JavaScriptCore/runtime/CatchScope.cpp
new file mode 100644 (file)
index 0000000..f7bb37a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CatchScope.h"
+
+namespace JSC {
+    
+#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+
+CatchScope::CatchScope(VM& vm, ExceptionEventLocation location)
+    : ExceptionScope(vm, location)
+{
+    m_vm.verifyExceptionCheckNeedIsSatisfied(m_recursionDepth, m_location);
+}
+
+CatchScope::~CatchScope()
+{
+    RELEASE_ASSERT(m_vm.m_topExceptionScope);
+    m_vm.verifyExceptionCheckNeedIsSatisfied(m_recursionDepth, m_location);
+}
+
+#endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/CatchScope.h b/Source/JavaScriptCore/runtime/CatchScope.h
new file mode 100644 (file)
index 0000000..9abf732
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CatchScope_h
+#define CatchScope_h
+
+#include "ExceptionScope.h"
+
+namespace JSC {
+    
+#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    
+// If a function can clear JS exceptions, it should declare a CatchScope at the
+// top of the function (as early as possible) using the DECLARE_CATCH_SCOPE macro.
+// Declaring a CatchScope in a function means that the function intends to clear
+// pending exceptions before returning to its caller.
+    
+class CatchScope : public ExceptionScope {
+public:
+    JS_EXPORT_PRIVATE CatchScope(VM&, ExceptionEventLocation);
+    CatchScope(const CatchScope&) = delete;
+    CatchScope(CatchScope&&) = default;
+
+    JS_EXPORT_PRIVATE ~CatchScope();
+
+    void clearException() { m_vm.clearException(); }
+};
+
+#define DECLARE_CATCH_SCOPE(vm__) \
+    JSC::CatchScope((vm__), JSC::ExceptionEventLocation(__FUNCTION__, __FILE__, __LINE__))
+
+#else // not ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+
+class CatchScope : public ExceptionScope {
+public:
+    ALWAYS_INLINE CatchScope(VM& vm)
+        : ExceptionScope(vm)
+    { }
+    CatchScope(const CatchScope&) = delete;
+    CatchScope(CatchScope&&) = default;
+
+    ALWAYS_INLINE void clearException() { m_vm.clearException(); }
+};
+
+#define DECLARE_CATCH_SCOPE(vm__) \
+    JSC::CatchScope((vm__))
+
+#endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+
+} // namespace JSC
+
+#endif // CatchScope_h
index 8b35453..a317090 100644 (file)
@@ -62,7 +62,9 @@ namespace JSC {
 
 #define BEGIN_NO_SET_PC() \
     VM& vm = exec->vm();      \
-    NativeCallFrameTracer tracer(&vm, exec)
+    NativeCallFrameTracer tracer(&vm, exec); \
+    auto throwScope = DECLARE_THROW_SCOPE(vm); \
+    UNUSED_PARAM(throwScope)
 
 #ifndef NDEBUG
 #define SET_PC_FOR_STUBS() do { \
@@ -99,10 +101,10 @@ namespace JSC {
 
 #define CHECK_EXCEPTION() do {                    \
         doExceptionFuzzingIfEnabled(exec, "CommonSlowPaths", pc);   \
-        if (UNLIKELY(vm.exception())) {           \
-            RETURN_TO_THROW(exec, pc);               \
+        if (UNLIKELY(throwScope.exception())) {   \
+            RETURN_TO_THROW(exec, pc);            \
             END_IMPL();                           \
-        }                                               \
+        }                                         \
     } while (false)
 
 #define END() do {                        \
@@ -144,7 +146,7 @@ namespace JSC {
 #define CALL_CHECK_EXCEPTION(exec, pc) do {                          \
         ExecState* cceExec = (exec);                                 \
         Instruction* ccePC = (pc);                                   \
-        if (UNLIKELY(vm.exception()))                                \
+        if (UNLIKELY(throwScope.exception()))                        \
             CALL_END_IMPL(cceExec, LLInt::callToThrow(cceExec));     \
     } while (false)
 
@@ -427,7 +429,7 @@ SLOW_PATH_DECL(slow_path_mul)
     JSValue left = OP_C(2).jsValue();
     JSValue right = OP_C(3).jsValue();
     double a = left.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     double b = right.toNumber(exec);
     JSValue result = jsNumber(a * b);
@@ -442,7 +444,7 @@ SLOW_PATH_DECL(slow_path_sub)
     JSValue left = OP_C(2).jsValue();
     JSValue right = OP_C(3).jsValue();
     double a = left.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     double b = right.toNumber(exec);
     JSValue result = jsNumber(a - b);
@@ -457,10 +459,10 @@ SLOW_PATH_DECL(slow_path_div)
     JSValue left = OP_C(2).jsValue();
     JSValue right = OP_C(3).jsValue();
     double a = left.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     double b = right.toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     JSValue result = jsNumber(a / b);
     RETURN_WITH_PROFILING(result, {
@@ -472,7 +474,7 @@ SLOW_PATH_DECL(slow_path_mod)
 {
     BEGIN();
     double a = OP_C(2).jsValue().toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     double b = OP_C(3).jsValue().toNumber(exec);
     RETURN(jsNumber(jsMod(a, b)));
@@ -482,10 +484,10 @@ SLOW_PATH_DECL(slow_path_pow)
 {
     BEGIN();
     double a = OP_C(2).jsValue().toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     double b = OP_C(3).jsValue().toNumber(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     RETURN(jsNumber(operationMathPow(a, b)));
 }
@@ -494,7 +496,7 @@ SLOW_PATH_DECL(slow_path_lshift)
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
     RETURN(jsNumber(a << (b & 31)));
@@ -504,7 +506,7 @@ SLOW_PATH_DECL(slow_path_rshift)
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
     RETURN(jsNumber(a >> (b & 31)));
@@ -514,7 +516,7 @@ SLOW_PATH_DECL(slow_path_urshift)
 {
     BEGIN();
     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
     RETURN(jsNumber(static_cast<int32_t>(a >> (b & 31))));
@@ -531,7 +533,7 @@ SLOW_PATH_DECL(slow_path_bitand)
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     int32_t b = OP_C(3).jsValue().toInt32(exec);
     RETURN(jsNumber(a & b));
@@ -541,7 +543,7 @@ SLOW_PATH_DECL(slow_path_bitor)
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     int32_t b = OP_C(3).jsValue().toInt32(exec);
     RETURN(jsNumber(a | b));
@@ -551,7 +553,7 @@ SLOW_PATH_DECL(slow_path_bitxor)
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
-    if (UNLIKELY(vm.exception()))
+    if (UNLIKELY(throwScope.exception()))
         RETURN(JSValue());
     int32_t b = OP_C(3).jsValue().toInt32(exec);
     RETURN(jsNumber(a ^ b));
index 358c37a..c26a8c7 100644 (file)
@@ -87,7 +87,7 @@ inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
         return baseObj->hasProperty(exec, i);
 
     auto property = propName.toPropertyKey(exec);
-    if (vm.exception())
+    if (scope.exception())
         return false;
     return baseObj->hasProperty(exec, property);
 }
index f6799c1..a272434 100644 (file)
@@ -43,7 +43,7 @@ void interpreterThrowInCaller(ExecState* exec, JSObject* error)
 
     throwException(exec, scope, error);
 #if LLINT_SLOW_PATH_TRACING
-    dataLog("Throwing exception ", vm->exception(), ".\n");
+    dataLog("Throwing exception ", scope.exception(), ".\n");
 #endif
 }
 
index e94239f..9548706 100644 (file)
@@ -87,16 +87,19 @@ bool checkModuleSyntax(ExecState* exec, const SourceCode& source, ParserError& e
 
 JSValue evaluate(ExecState* exec, const SourceCode& source, JSValue thisValue, NakedPtr<Exception>& returnedException)
 {
-    JSLockHolder lock(exec);
-    RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!exec->vm().isCollectorBusy());
+    VM& vm = exec->vm();
+    JSLockHolder lock(vm);
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
+    RELEASE_ASSERT(!vm.isCollectorBusy());
 
     CodeProfiling profile(source);
 
     ProgramExecutable* program = ProgramExecutable::create(exec, source);
+    ASSERT(scope.exception() || program);
     if (!program) {
-        returnedException = exec->vm().exception();
-        exec->vm().clearException();
+        returnedException = scope.exception();
+        scope.clearException();
         return jsUndefined();
     }
 
@@ -105,9 +108,9 @@ JSValue evaluate(ExecState* exec, const SourceCode& source, JSValue thisValue, N
     JSObject* thisObj = jsCast<JSObject*>(thisValue.toThis(exec, NotStrictMode));
     JSValue result = exec->interpreter()->execute(program, exec, thisObj);
 
-    if (exec->hadException()) {
-        returnedException = exec->exception();
-        exec->clearException();
+    if (scope.exception()) {
+        returnedException = scope.exception();
+        scope.clearException();
         return jsUndefined();
     }
 
@@ -147,9 +150,11 @@ static Symbol* createSymbolForEntryPointModule(VM& vm)
 
 static JSInternalPromise* rejectPromise(ExecState* exec, JSGlobalObject* globalObject)
 {
-    ASSERT(exec->hadException());
-    JSValue exception = exec->exception()->value();
-    exec->clearException();
+    VM& vm = exec->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    ASSERT(scope.exception());
+    JSValue exception = scope.exception()->value();
+    scope.clearException();
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     deferred->reject(exec, exception);
     return deferred->promise();
@@ -176,17 +181,19 @@ JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const String& moduleNa
 
 JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const SourceCode& source, JSValue initiator)
 {
-    JSLockHolder lock(exec);
-    RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!exec->vm().isCollectorBusy());
+    VM& vm = exec->vm();
+    JSLockHolder lock(vm);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
+    RELEASE_ASSERT(!vm.isCollectorBusy());
 
-    Symbol* key = createSymbolForEntryPointModule(exec->vm());
+    Symbol* key = createSymbolForEntryPointModule(vm);
 
     JSGlobalObject* globalObject = exec->vmEntryGlobalObject();
 
     // Insert the given source code to the ModuleLoader registry as the fetched registry entry.
     globalObject->moduleLoader()->provide(exec, key, JSModuleLoader::Status::Fetch, source.view().toString());
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return rejectPromise(exec, globalObject);
 
     return loadAndEvaluateModule(lock, exec, globalObject, key, jsUndefined(), initiator);
@@ -213,18 +220,20 @@ JSInternalPromise* loadModule(ExecState* exec, const String& moduleName, JSValue
 
 JSInternalPromise* loadModule(ExecState* exec, const SourceCode& source, JSValue initiator)
 {
-    JSLockHolder lock(exec);
-    RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!exec->vm().isCollectorBusy());
+    VM& vm = exec->vm();
+    JSLockHolder lock(vm);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
+    RELEASE_ASSERT(!vm.isCollectorBusy());
 
-    Symbol* key = createSymbolForEntryPointModule(exec->vm());
+    Symbol* key = createSymbolForEntryPointModule(vm);
 
     JSGlobalObject* globalObject = exec->vmEntryGlobalObject();
 
     // Insert the given source code to the ModuleLoader registry as the fetched registry entry.
     // FIXME: Introduce JSSourceCode object to wrap around this source.
     globalObject->moduleLoader()->provide(exec, key, JSModuleLoader::Status::Fetch, source.view().toString());
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return rejectPromise(exec, globalObject);
 
     return loadModule(lock, exec, globalObject, key, jsUndefined(), initiator);
index 137aba3..a0fa2d9 100644 (file)
@@ -196,12 +196,14 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTrace(ExecState* exec)
 
 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncAssert(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
     if (!client)
         return JSValue::encode(jsUndefined());
 
     bool condition = exec->argument(0).toBoolean(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     if (condition)
@@ -225,6 +227,8 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncCount(ExecState* exec)
 
 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfile(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
     if (!client)
         return JSValue::encode(jsUndefined());
@@ -236,7 +240,7 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfile(ExecState* exec)
     }
 
     const String& title(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)));
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     client->profile(exec, title);
@@ -245,6 +249,8 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfile(ExecState* exec)
 
 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfileEnd(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
     if (!client)
         return JSValue::encode(jsUndefined());
@@ -256,7 +262,7 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfileEnd(ExecState* exec)
     }
 
     const String& title(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)));
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     client->profileEnd(exec, title);
@@ -265,6 +271,8 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfileEnd(ExecState* exec)
 
 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTakeHeapSnapshot(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
     if (!client)
         return JSValue::encode(jsUndefined());
@@ -276,7 +284,7 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTakeHeapSnapshot(ExecState*
     }
 
     const String& title(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)));
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     client->takeHeapSnapshot(exec, title);
@@ -292,6 +300,8 @@ static String valueOrDefaultLabelString(ExecState* exec, JSValue value)
 
 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTime(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
     if (!client)
         return JSValue::encode(jsUndefined());
@@ -301,7 +311,7 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTime(ExecState* exec)
         title = ASCIILiteral("default");
     else {
         title = valueOrDefaultLabelString(exec, exec->argument(0));
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 
@@ -311,6 +321,8 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTime(ExecState* exec)
 
 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTimeEnd(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
     if (!client)
         return JSValue::encode(jsUndefined());
@@ -320,7 +332,7 @@ static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTimeEnd(ExecState* exec)
         title =  ASCIILiteral("default");
     else {
         title = valueOrDefaultLabelString(exec, exec->argument(0));
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 
index 3a39788..6444913 100644 (file)
@@ -147,6 +147,7 @@ static double millisecondsFromComponents(ExecState* exec, const ArgList& args, W
 JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, JSValue newTarget, const ArgList& args)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     int numArgs = args.size();
 
     double value;
@@ -167,7 +168,7 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, JSValue n
         value = millisecondsFromComponents(exec, args, WTF::LocalTime);
 
     Structure* dateStructure = InternalFunction::createSubclassStructure(exec, newTarget, globalObject->dateStructure());
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
 
     return DateInstance::create(vm, dateStructure, value);
@@ -202,10 +203,12 @@ CallType DateConstructor::getCallData(JSCell*, CallData& callData)
 
 EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     String dateStr = exec->argument(0).toString(exec)->value(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
-    return JSValue::encode(jsNumber(parseDate(exec->vm(), dateStr)));
+    return JSValue::encode(jsNumber(parseDate(vm, dateStr)));
 }
 
 EncodedJSValue JSC_HOST_CALL dateNow(ExecState* exec)
index 768dd46..5ef4e72 100644 (file)
@@ -603,7 +603,8 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncToPrimitiveSymbol(ExecState* exec)
 {
-    auto scope = DECLARE_THROW_SCOPE(exec->vm());
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
     if (!thisValue.isObject())
         return throwVMTypeError(exec, scope, "Date.prototype[Symbol.toPrimitive] expected |this| to be an object.");
@@ -614,7 +615,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToPrimitiveSymbol(ExecState* exec)
 
     JSValue hintValue = exec->uncheckedArgument(0);
     PreferredPrimitiveType type = toPreferredPrimitiveType(exec, hintValue);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
 
     if (type == NoPreference)
@@ -1123,20 +1124,21 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
 {
-    auto scope = DECLARE_THROW_SCOPE(exec->vm());
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
     JSObject* object = jsCast<JSObject*>(thisValue.toThis(exec, NotStrictMode));
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsNull());
 
     JSValue timeValue = object->toPrimitive(exec, PreferNumber);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsNull());
     if (timeValue.isNumber() && !(timeValue.isInt32() || std::isfinite(timeValue.asDouble())))
         return JSValue::encode(jsNull());
 
-    JSValue toISOValue = object->get(exec, exec->vm().propertyNames->toISOString);
-    if (exec->hadException())
+    JSValue toISOValue = object->get(exec, vm.propertyNames->toISOString);
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsNull());
 
     CallData callData;
@@ -1145,7 +1147,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
         return throwVMTypeError(exec, scope, ASCIILiteral("toISOString is not a function"));
 
     JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsNull());
     if (result.isObject())
         return throwVMTypeError(exec, scope, ASCIILiteral("toISOString did not return a primitive value"));
index 2ad6b7b..cea0805 100644 (file)
@@ -50,9 +50,11 @@ void ErrorConstructor::finishCreation(VM& vm, ErrorPrototype* errorPrototype)
 
 EncodedJSValue JSC_HOST_CALL Interpreter::constructWithErrorConstructor(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
     Structure* errorStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), asInternalFunction(exec->callee())->globalObject()->errorStructure());
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(JSValue());
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message, nullptr, TypeNothing, false));
 }
index 6c0ea29..f94f13b 100644 (file)
@@ -158,6 +158,7 @@ void ErrorInstance::finishCreation(ExecState* exec, VM& vm, const String& messag
 String ErrorInstance::sanitizedToString(ExecState* exec)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue nameValue;
     auto namePropertName = vm.propertyNames->name;
@@ -177,14 +178,14 @@ String ErrorInstance::sanitizedToString(ExecState* exec)
         }
         currentObj = obj->getPrototypeDirect();
     }
-    ASSERT(!vm.exception());
+    ASSERT(!scope.exception());
 
     String nameString;
     if (!nameValue)
         nameString = ASCIILiteral("Error");
     else {
         nameString = nameValue.toString(exec)->value(exec);
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return String();
     }
 
@@ -193,14 +194,14 @@ String ErrorInstance::sanitizedToString(ExecState* exec)
     PropertySlot messageSlot(this, PropertySlot::InternalMethodType::VMInquiry);
     if (JSObject::getOwnPropertySlot(this, exec, messagePropertName, messageSlot) && messageSlot.isValue())
         messageValue = messageSlot.getValue(exec, messagePropertName);
-    ASSERT(!vm.exception());
+    ASSERT(!scope.exception());
 
     String messageString;
     if (!messageValue)
         messageString = String();
     else {
         messageString = messageValue.toString(exec)->value(exec);
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return String();
     }
 
index 6403dd2..da0167d 100644 (file)
@@ -85,7 +85,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
 
     // 3. Let name be the result of calling the [[Get]] internal method of O with argument "name".
     JSValue name = thisObj->get(exec, exec->propertyNames().name);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     // 4. If name is undefined, then let name be "Error"; else let name be ToString(name).
@@ -94,13 +94,13 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
         nameString = ASCIILiteral("Error");
     else {
         nameString = name.toString(exec)->value(exec);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 
     // 5. Let msg be the result of calling the [[Get]] internal method of O with argument "message".
     JSValue message = thisObj->get(exec, exec->propertyNames().message);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     // (sic)
@@ -111,7 +111,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
         messageString = String();
     else {
         messageString = message.toString(exec)->value(exec);
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
     }
 
diff --git a/Source/JavaScriptCore/runtime/ExceptionEventLocation.cpp b/Source/JavaScriptCore/runtime/ExceptionEventLocation.cpp
new file mode 100644 (file)
index 0000000..c95d3eb
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ExceptionEventLocation.h"
+
+#include <wtf/PrintStream.h>
+
+namespace WTF {
+    
+void printInternal(PrintStream& out, JSC::ExceptionEventLocation location)
+{
+    out.print(location.functionName, " @ ", location.file, ":", location.line);
+}
+
+} // namespace WTF
+
@@ -27,9 +27,9 @@
 
 namespace JSC {
 
-struct ThrowScopeLocation {
-    ThrowScopeLocation() { }
-    ThrowScopeLocation(const char* functionName, const char* file, unsigned line)
+struct ExceptionEventLocation {
+    ExceptionEventLocation() { }
+    ExceptionEventLocation(const char* functionName, const char* file, unsigned line)
         : functionName(functionName)
         , file(file)
         , line(line)
@@ -41,3 +41,11 @@ struct ThrowScopeLocation {
 };
 
 } // namespace JSC
+
+namespace WTF {
+    
+class PrintStream;
+
+void printInternal(PrintStream&, JSC::ExceptionEventLocation);
+    
+} // namespace WTF
index 3a3edb8..b66333d 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef ExceptionHelpers_h
 #define ExceptionHelpers_h
 
+#include "CatchScope.h"
 #include "ErrorInstance.h"
 #include "JSObject.h"
 #include "ThrowScope.h"
diff --git a/Source/JavaScriptCore/runtime/ExceptionScope.cpp b/Source/JavaScriptCore/runtime/ExceptionScope.cpp
new file mode 100644 (file)
index 0000000..0a86a39
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ExceptionScope.h"
+
+#include "Exception.h"
+
+namespace JSC {
+    
+#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    
+ExceptionScope::ExceptionScope(VM& vm, ExceptionEventLocation location)
+    : m_vm(vm)
+    , m_previousScope(vm.m_topExceptionScope)
+    , m_location(location)
+    , m_recursionDepth(m_previousScope ? m_previousScope->m_recursionDepth + 1 : 0)
+{
+    m_vm.m_topExceptionScope = this;
+}
+
+ExceptionScope::~ExceptionScope()
+{
+    RELEASE_ASSERT(m_vm.m_topExceptionScope);
+    m_vm.m_topExceptionScope = m_previousScope;
+}
+
+#endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ExceptionScope.h b/Source/JavaScriptCore/runtime/ExceptionScope.h
new file mode 100644 (file)
index 0000000..4adedc5
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ExceptionScope_h
+#define ExceptionScope_h
+
+#include "VM.h"
+
+namespace JSC {
+    
+class Exception;
+    
+#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    
+class ExceptionScope {
+public:
+    VM& vm() const { return m_vm; }
+    unsigned recursionDepth() const { return m_recursionDepth; }
+    Exception* exception() { return m_vm.exception(); }
+    
+protected:
+    ExceptionScope(VM&, ExceptionEventLocation);
+    ExceptionScope(const ExceptionScope&) = delete;
+    ExceptionScope(ExceptionScope&&) = default;
+    ~ExceptionScope();
+
+    VM& m_vm;
+    ExceptionScope* m_previousScope;
+    ExceptionEventLocation m_location;
+    unsigned m_recursionDepth;
+};
+    
+#else // not ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    
+class ExceptionScope {
+public:
+    ALWAYS_INLINE VM& vm() const { return m_vm; }
+    ALWAYS_INLINE Exception* exception() { return m_vm.exception(); }
+
+protected:
+    ALWAYS_INLINE ExceptionScope(VM& vm)
+        : m_vm(vm)
+    { }
+    ExceptionScope(const ExceptionScope&) = delete;
+    ExceptionScope(ExceptionScope&&) = default;
+
+    VM& m_vm;
+};
+    
+#endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    
+} // namespace JSC
+
+#endif // ExceptionScope_h
index a74b8b3..3d57c90 100644 (file)
@@ -126,7 +126,7 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(
     }
 
     Structure* subclassStructure = InternalFunction::createSubclassStructure(exec, newTarget, globalObject->functionStructure());
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
 
     return JSFunction::create(vm, function, globalObject->globalScope(), subclassStructure);
index 7e2a5c9..0dbcb21 100644 (file)
@@ -160,7 +160,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec)
     // Else set the length own property of F to 0.
     unsigned length = 0;
     if (targetObject->hasOwnProperty(exec, exec->propertyNames().length)) {
-        if (exec->hadException())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(jsUndefined());
 
         // a. Let L be the length property of Target minus the length of A.
index 654fb54..68898a9 100644 (file)
@@ -219,13 +219,16 @@ bool GenericArguments<Type>::defineOwnProperty(JSObject* object, ExecState* exec
 template<typename Type>
 void GenericArguments<Type>::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     Type* thisObject = static_cast<Type*>(this);
     for (unsigned i = 0; i < length; ++i) {
         if (thisObject->canAccessIndexQuickly(i + offset))
             exec->r(firstElementDest + i) = thisObject->getIndexQuickly(i + offset);
         else {
             exec->r(firstElementDest + i) = get(exec, i + offset);
-            if (UNLIKELY(exec->vm().exception()))
+            if (UNLIKELY(scope.exception()))
                 return;
         }
     }
index a51c217..4302bfc 100644 (file)
@@ -73,15 +73,17 @@ GetterSetter* GetterSetter::withSetter(VM& vm, JSGlobalObject* globalObject, JSO
 
 JSValue callGetter(ExecState* exec, JSValue base, JSValue getterSetter)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     // FIXME: Some callers may invoke get() without checking for an exception first.
     // We work around that by checking here.
-    if (exec->hadException())
-        return exec->exception()->value();
+    if (UNLIKELY(scope.exception()))
+        return scope.exception()->value();
 
     JSObject* getter = jsCast<GetterSetter*>(getterSetter)->getter();
 
     CallData callData;
-    CallType callType = getter->methodTable(exec->vm())->getCallData(getter, callData);
+    CallType callType = getter->methodTable(vm)->getCallData(getter, callData);
     return call(exec, getter, callType, callData, base, ArgList());
 }
 
index 204178c..d7cf03f 100644 (file)
@@ -83,9 +83,11 @@ void InspectorInstrumentationObject::disable(VM& vm)
 
 EncodedJSValue JSC_HOST_CALL inspectorInstrumentationObjectLog(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue target = exec->argument(0);
     String value = target.toString(exec)->value(exec);
-    if (exec->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
     dataLog(value, "\n");
     return JSValue::encode(jsUndefined());
index 6d7ecf3..33716db 100644 (file)
@@ -97,6 +97,7 @@ Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue ne
 {
 
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     // We allow newTarget == JSValue() because the API needs to be able to create classes without having a real JS frame.
     // Since we don't allow subclassing in the API we just treat newTarget == JSValue() as newTarget == exec->callee()
     ASSERT(!newTarget || newTarget.isConstructor());
@@ -112,13 +113,13 @@ Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue ne
 
             // Note, Reflect.construct might cause the profile to churn but we don't care.
             JSValue prototypeValue = newTarget.get(exec, exec->propertyNames().prototype);
-            if (UNLIKELY(vm.exception()))
+            if (UNLIKELY(scope.exception()))
                 return nullptr;
             if (JSObject* prototype = jsDynamicCast<JSObject*>(prototypeValue))
                 return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
         } else {
             JSValue prototypeValue = newTarget.get(exec, exec->propertyNames().prototype);
-            if (UNLIKELY(vm.exception()))
+            if (UNLIKELY(scope.exception()))
                 return nullptr;
             if (JSObject* prototype = jsDynamicCast<JSObject*>(prototypeValue)) {
                 // This only happens if someone Reflect.constructs our builtin constructor with another builtin constructor as the new.target.
index feb1f64..c2139ca 100644 (file)
@@ -162,6 +162,9 @@ static Vector<String> searchLocaleData(const String&, size_t keyIndex)
 
 void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue optionsValue)
 {
+    VM& vm = state.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // 10.1.1 InitializeCollator (collator, locales, options) (ECMA-402 2.0)
     // 1. If collator has an [[initializedIntlObject]] internal slot with value true, throw a TypeError exception.
     // 2. Set collator.[[initializedIntlObject]] to true.
@@ -169,7 +172,7 @@ void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue
     // 3. Let requestedLocales be CanonicalizeLocaleList(locales).
     auto requestedLocales = canonicalizeLocaleList(state, locales);
     // 4. ReturnIfAbrupt(requestedLocales).
-    if (state.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
 
     // 5. If options is undefined, then
@@ -181,14 +184,14 @@ void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue
         // a. Let options be ToObject(options).
         options = optionsValue.toObject(&state);
         // b. ReturnIfAbrupt(options).
-        if (state.hadException())
+        if (UNLIKELY(scope.exception()))
             return;
     }
 
     // 7. Let u be GetOption(options, "usage", "string", «"sort", "search"», "sort").
-    String usageString = intlStringOption(state, options, state.vm().propertyNames->usage, { "sort", "search" }, "usage must be either \"sort\" or \"search\"", "sort");
+    String usageString = intlStringOption(state, options, vm.propertyNames->usage, { "sort", "search" }, "usage must be either \"sort\" or \"search\"", "sort");
     // 8. ReturnIfAbrupt(u).
-    if (state.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     // 9. Set collator.[[usage]] to u.
     if (usageString == "sort")
@@ -212,9 +215,9 @@ void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue
     HashMap<String, String> opt;
 
     // 13. Let matcher be GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit").
-    String matcher = intlStringOption(state, options, state.vm().propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
+    String matcher = intlStringOption(state, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
     // 14. ReturnIfAbrupt(matcher).
-    if (state.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     // 15. Set opt.[[localeMatcher]] to matcher.
     opt.add(ASCIILiteral("localeMatcher"), matcher);
@@ -233,16 +236,16 @@ void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue
     {
         String numericString;
         bool usesFallback;
-        bool numeric = intlBooleanOption(state, options, state.vm().propertyNames->numeric, usesFallback);
-        if (state.hadException())
+        bool numeric = intlBooleanOption(state, options, vm.propertyNames->numeric, usesFallback);
+        if (UNLIKELY(scope.exception()))
             return;
         if (!usesFallback)
             numericString = ASCIILiteral(numeric ? "true" : "false");
         opt.add(ASCIILiteral("kn"), numericString);
     }
     {
-        String caseFirst = intlStringOption(state, options, state.vm().propertyNames->caseFirst, { "upper", "lower", "false" }, "caseFirst must be either \"upper\", \"lower\", or \"false\"", nullptr);
-        if (state.hadException())
+        String caseFirst = intlStringOption(state, options, vm.propertyNames->caseFirst, { "upper", "lower", "false" }, "caseFirst must be either \"upper\", \"lower\", or \"false\"", nullptr);
+        if (UNLIKELY(scope.exception()))
             return;
         opt.add(ASCIILiteral("kf"), caseFirst);
     }
@@ -277,9 +280,9 @@ void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue
     m_numeric = (result.get(ASCIILiteral("kn")) == "true");
 
     // 24. Let s be GetOption(options, "sensitivity", "string", «"base", "accent", "case", "variant"», undefined).
-    String sensitivityString = intlStringOption(state, options, state.vm().propertyNames->sensitivity, { "base", "accent", "case", "variant" }, "sensitivity must be either \"base\", \"accent\", \"case\", or \"variant\"", nullptr);
+    String sensitivityString = intlStringOption(state, options, vm.propertyNames->sensitivity, { "base", "accent", "case", "variant" }, "sensitivity must be either \"base\", \"accent\", \"case\", or \"variant\"", nullptr);
     // 25. ReturnIfAbrupt(s).
-    if (state.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     // 26. If s is undefined, then
     // a. If u is "sort", then let s be "variant".
@@ -300,11 +303,11 @@ void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue
 
     // 28. Let ip be GetOption(options, "ignorePunctuation", "boolean", undefined, false).
     bool usesFallback;
-    bool ignorePunctuation = intlBooleanOption(state, options, state.vm().propertyNames->ignorePunctuation, usesFallback);
+    bool ignorePunctuation = intlBooleanOption(state, options, vm.propertyNames->ignorePunctuation, usesFallback);
     if (usesFallback)
         ignorePunctuation = false;
     // 29. ReturnIfAbrupt(ip).
-    if (state.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     // 30. Set collator.[[ignorePunctuation]] to ip.
     m_ignorePunctuation = ignorePunctuation;
@@ -318,11 +321,13 @@ void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue
 
 void IntlCollator::createCollator(ExecState& state)
 {
+    VM& vm = state.vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
     ASSERT(!m_collator);
 
     if (!m_initializedCollator) {
         initializeCollator(state, jsUndefined(), jsUndefined());
-        ASSERT(!state.hadException());
+        ASSERT_UNUSED(scope, !scope.exception());
     }
 
     UErrorCode status = U_ZERO_ERROR;
@@ -416,6 +421,9 @@ const char* IntlCollator::sensitivityString(Sensitivity sensitivity)
 
 JSObject* IntlCollator::resolvedOptions(ExecState& state)
 {
+    VM& vm = state.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // 10.3.5 Intl.Collator.prototype.resolvedOptions() (ECMA-402 2.0)
     // The function returns a new object whose properties and attributes are set as if
     // constructed by an object literal assigning to each of the following properties the
@@ -427,10 +435,9 @@ JSObject* IntlCollator::resolvedOptions(ExecState& state)
 
     if (!m_initializedCollator) {
         initializeCollator(state, jsUndefined(), jsUndefined());
-        ASSERT(!state.hadException());
+        ASSERT_UNUSED(scope, !scope.exception());
     }
 
-    VM& vm = state.vm();
     JSObject* options = constructEmptyObject(&state);
     options->putDirect(vm, vm.propertyNames->locale, jsString(&state, m_locale));
     options->putDirect(vm, vm.propertyNames->usage, jsNontrivialString(&state, ASCIILiteral(usageString(m_usage))));
index f11cca0..8df42f5 100644 (file)
@@ -83,14 +83,16 @@ void IntlCollatorConstructor::finishCreation(VM& vm, IntlCollatorPrototype* coll
 
 static EncodedJSValue JSC_HOST_CALL constructIntlCollator(ExecState* state)
 {
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     // 10.1.2 Intl.Collator ([locales [, options]]) (ECMA-402 2.0)
     // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
     // 2. Let collator be OrdinaryCreateFromConstructor(newTarget, %CollatorPrototype%).
     // 3. ReturnIfAbrupt(collator).
     Structure* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), jsCast<IntlCollatorConstructor*>(state->callee())->collatorStructure());
-    if (state->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
-    IntlCollator* collator = IntlCollator::create(state->vm(), structure);
+    IntlCollator* collator = IntlCollator::create(vm, structure);
     ASSERT(collator);
 
     // 4. Return InitializeCollator(collator, locales, options).
@@ -134,13 +136,15 @@ CallType IntlCollatorConstructor::getCallData(JSCell*, CallData& callData)
 
 EncodedJSValue JSC_HOST_CALL IntlCollatorConstructorFuncSupportedLocalesOf(ExecState* state)
 {
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     // 10.2.2 Intl.Collator.supportedLocalesOf(locales [, options]) (ECMA-402 2.0)
 
     // 1. Let requestedLocales be CanonicalizeLocaleList(locales).
     Vector<String> requestedLocales = canonicalizeLocaleList(*state, state->argument(0));
 
     // 2. ReturnIfAbrupt(requestedLocales).
-    if (state->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     // 3. Return SupportedLocales(%Collator%.[[availableLocales]], requestedLocales, options).
index 489b9f7..058e73a 100644 (file)
@@ -78,6 +78,8 @@ void IntlCollatorPrototype::finishCreation(VM& vm)
 
 static EncodedJSValue JSC_HOST_CALL IntlCollatorFuncCompare(ExecState* state)
 {
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     // 10.3.4 Collator Compare Functions (ECMA-402 2.0)
     // 1. Let collator be the this value.
     // 2. Assert: Type(collator) is Object and collator has an [[initializedCollator]] internal slot whose value is true.
@@ -88,13 +90,13 @@ static EncodedJSValue JSC_HOST_CALL IntlCollatorFuncCompare(ExecState* state)
     // 5. Let X be ToString(x).
     JSString* x = state->argument(0).toString(state);
     // 6. ReturnIfAbrupt(X).
-    if (state->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     // 7. Let Y be ToString(y).
     JSString* y = state->argument(1).toString(state);
     // 8. ReturnIfAbrupt(Y).
-    if (state->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
 
     // 9. Return CompareStrings(collator, X, Y).
@@ -122,7 +124,7 @@ EncodedJSValue JSC_HOST_CALL IntlCollatorPrototypeGetterCompare(ExecState* state
 
         // c. Let bc be BoundFunctionCreate(F, «this value»).
         boundCompare = JSBoundFunction::create(vm, state, globalObject, targetObject, collator, nullptr, 2, ASCIILiteral("compare"));
-        if (vm.exception())
+        if (UNLIKELY(scope.exception()))
             return JSValue::encode(JSValue());
         // d. Set collator.[[boundCompare]] to bc.
         collator->setBoundCompare(vm, boundCompare);
index 85913af..8488b77 100644 (file)
@@ -215,6 +215,7 @@ static JSObject* toDateTimeOptionsAnyDate(ExecState& exec, JSValue originalOptio
 {
     // 12.1.1 ToDateTimeOptions abstract operation (ECMA-402 2.0)
     VM& vm = exec.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     // 1. If options is undefined, then let options be null, else let options be ToObject(options).
     // 2. ReturnIfAbrupt(options).
@@ -224,7 +225,7 @@ static JSObject* toDateTimeOptionsAnyDate(ExecState& exec, JSValue originalOptio
         options = constructEmptyObject(&exec, exec.lexicalGlobalObject()->nullPrototypeObjectStructure());
     else {
         JSObject* originalToObject = originalOptions.toObject(&exec);
-        if (exec.hadException())
+        if (UNLIKELY(scope.exception()))
             return nullptr;
         options = constructEmptyObject(&exec, originalToObject);
     }
@@ -241,25 +242,25 @@ static JSObject* toDateTimeOptionsAnyDate(ExecState& exec, JSValue originalOptio
     // iii. ReturnIfAbrupt(value).
     // iv. If value is not undefined, then let needDefaults be false.
     JSValue weekday = options->get(&exec, vm.propertyNames->weekday);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
     if (!weekday.isUndefined())
         needDefaults = false;
 
     JSValue year = options->get(&exec, vm.propertyNames->year);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
     if (!year.isUndefined())
         needDefaults = false;
 
     JSValue month = options->get(&exec, vm.propertyNames->month);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
     if (!month.isUndefined())
         needDefaults = false;
 
     JSValue day = options->get(&exec, vm.propertyNames->day);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
     if (!day.isUndefined())
         needDefaults = false;
@@ -273,19 +274,19 @@ static JSObject* toDateTimeOptionsAnyDate(ExecState& exec, JSValue originalOptio
     // iii. ReturnIfAbrupt(value).
     // iv. If value is not undefined, then let needDefaults be false.
     JSValue hour = options->get(&exec, vm.propertyNames->hour);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
     if (!hour.isUndefined())
         needDefaults = false;
 
     JSValue minute = options->get(&exec, vm.propertyNames->minute);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
     if (!minute.isUndefined())
         needDefaults = false;
 
     JSValue second = options->get(&exec, vm.propertyNames->second);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return nullptr;
     if (!second.isUndefined())
         needDefaults = false;
@@ -299,15 +300,15 @@ static JSObject* toDateTimeOptionsAnyDate(ExecState& exec, JSValue originalOptio
         JSString* numeric = jsNontrivialString(&exec, ASCIILiteral("numeric"));
 
         options->putDirect(vm, vm.propertyNames->year, numeric);
-        if (exec.hadException())
+        if (UNLIKELY(scope.exception()))
             return nullptr;
 
         options->putDirect(vm, vm.propertyNames->month, numeric);
-        if (exec.hadException())
+        if (UNLIKELY(scope.exception()))
             return nullptr;
 
         options->putDirect(vm, vm.propertyNames->day, numeric);
-        if (exec.hadException())
+        if (UNLIKELY(scope.exception()))
             return nullptr;
     }
 
@@ -428,13 +429,13 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     // 3. Let requestedLocales be CanonicalizeLocaleList(locales).
     Vector<String> requestedLocales = canonicalizeLocaleList(exec, locales);
     // 4. ReturnIfAbrupt(requestedLocales),
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
 
     // 5. Let options be ToDateTimeOptions(options, "any", "date").
     JSObject* options = toDateTimeOptionsAnyDate(exec, originalOptions);
     // 6. ReturnIfAbrupt(options).
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
 
     // 7. Let opt be a new Record.
@@ -443,7 +444,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     // 8. Let matcher be GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit").
     String localeMatcher = intlStringOption(exec, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
     // 9. ReturnIfAbrupt(matcher).
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     // 10. Set opt.[[localeMatcher]] to matcher.
     localeOpt.add(vm.propertyNames->localeMatcher.string(), localeMatcher);
@@ -472,7 +473,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     // 17. Let tz be Get(options, "timeZone").
     JSValue tzValue = options->get(&exec, vm.propertyNames->timeZone);
     // 18. ReturnIfAbrupt(tz).
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
 
     // 19. If tz is not undefined, then
@@ -481,7 +482,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
         // a. Let tz be ToString(tz).
         String originalTz = tzValue.toWTFString(&exec);
         // b. ReturnIfAbrupt(tz).
-        if (exec.hadException())
+        if (UNLIKELY(scope.exception()))
             return;
         // c. If the result of IsValidTimeZoneName(tz) is false, then i. Throw a RangeError exception.
         // d. Let tz be CanonicalizeTimeZoneName(tz).
@@ -514,7 +515,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     auto shortLong = { "short", "long" };
 
     String weekday = intlStringOption(exec, options, vm.propertyNames->weekday, narrowShortLong, "weekday must be \"narrow\", \"short\", or \"long\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     if (!weekday.isNull()) {
         if (weekday == "narrow")
@@ -526,7 +527,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     }
 
     String era = intlStringOption(exec, options, vm.propertyNames->era, narrowShortLong, "era must be \"narrow\", \"short\", or \"long\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     if (!era.isNull()) {
         if (era == "narrow")
@@ -538,7 +539,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     }
 
     String year = intlStringOption(exec, options, vm.propertyNames->year, twoDigitNumeric, "year must be \"2-digit\" or \"numeric\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     if (!year.isNull()) {
         if (year == "2-digit")
@@ -548,7 +549,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     }
 
     String month = intlStringOption(exec, options, vm.propertyNames->month, twoDigitNumericNarrowShortLong, "month must be \"2-digit\", \"numeric\", \"narrow\", \"short\", or \"long\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     if (!month.isNull()) {
         if (month == "2-digit")
@@ -564,7 +565,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     }
 
     String day = intlStringOption(exec, options, vm.propertyNames->day, twoDigitNumeric, "day must be \"2-digit\" or \"numeric\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     if (!day.isNull()) {
         if (day == "2-digit")
@@ -574,7 +575,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     }
 
     String hour = intlStringOption(exec, options, vm.propertyNames->hour, twoDigitNumeric, "hour must be \"2-digit\" or \"numeric\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
 
     // We need hour12 to make the hour skeleton pattern decision, so do this early.
@@ -582,7 +583,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     bool isHour12Undefined;
     bool hr12 = intlBooleanOption(exec, options, vm.propertyNames->hour12, isHour12Undefined);
     // 33. ReturnIfAbrupt(hr12).
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
 
     if (!hour.isNull()) {
@@ -605,7 +606,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     }
 
     String minute = intlStringOption(exec, options, vm.propertyNames->minute, twoDigitNumeric, "minute must be \"2-digit\" or \"numeric\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     if (!minute.isNull()) {
         if (minute == "2-digit")
@@ -615,7 +616,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     }
 
     String second = intlStringOption(exec, options, vm.propertyNames->second, twoDigitNumeric, "second must be \"2-digit\" or \"numeric\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     if (!second.isNull()) {
         if (second == "2-digit")
@@ -625,7 +626,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     }
 
     String timeZoneName = intlStringOption(exec, options, vm.propertyNames->timeZoneName, shortLong, "timeZoneName must be \"short\" or \"long\"", nullptr);
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
     if (!timeZoneName.isNull()) {
         if (timeZoneName == "short")
@@ -639,7 +640,7 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local
     // 26. Let matcher be GetOption(options, "formatMatcher", "string", «"basic", "best fit"», "best fit").
     intlStringOption(exec, options, vm.propertyNames->formatMatcher, { "basic", "best fit" }, "formatMatcher must be either \"basic\" or \"best fit\"", "best fit");
     // 27. ReturnIfAbrupt(matcher).
-    if (exec.hadException())
+    if (UNLIKELY(scope.exception()))
         return;
 
     // Always use ICU date format generator, rather than our own pattern list and matcher.
@@ -834,15 +835,17 @@ const char* IntlDateTimeFormat::timeZoneNameString(TimeZoneName timeZoneName)
 
 JSObject* IntlDateTimeFormat::resolvedOptions(ExecState& exec)
 {
+    VM& vm = exec.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // 12.3.5 Intl.DateTimeFormat.prototype.resolvedOptions() (ECMA-402 2.0)
     // The function returns a new object whose properties and attributes are set as if constructed by an object literal assigning to each of the following properties the value of the corresponding internal slot of this DateTimeFormat object (see 12.4): locale, calendar, numberingSystem, timeZone, hour12, weekday, era, year, month, day, hour, minute, second, and timeZoneName. Properties whose corresponding internal slots are not present are not assigned.
     // Note: In this version of the ECMAScript 2015 Internationalization API, the timeZone property will be the name of the default time zone if no timeZone property was provided in the options object provided to the Intl.DateTimeFormat constructor. The previous version left the timeZone property undefined in this case.
     if (!m_initializedDateTimeFormat) {
         initializeDateTimeFormat(exec, jsUndefined(), jsUndefined());
-        ASSERT(!exec.hadException());
+        ASSERT_UNUSED(scope, !scope.exception());
     }
 
-    VM& vm = exec.vm();
     JSObject* options = constructEmptyObject(&exec);
     options->putDirect(vm, vm.propertyNames->locale, jsNontrivialString(&exec, m_locale));
     options->putDirect(vm, vm.propertyNames->calendar, jsNontrivialString(&exec, m_calendar));
@@ -889,7 +892,7 @@ JSValue IntlDateTimeFormat::format(ExecState& exec, double value)
     // 12.3.4 FormatDateTime abstract operation (ECMA-402 2.0)
     if (!m_initializedDateTimeFormat) {
         initializeDateTimeFormat(exec, jsUndefined(), jsUndefined());
-        ASSERT(!exec.hadException());
+        ASSERT(!scope.exception());
     }
 
     // 1. If x is not a finite Number, then throw a RangeError exception.
index da83a71..1bf6f09 100644 (file)
@@ -83,14 +83,16 @@ void IntlDateTimeFormatConstructor::finishCreation(VM& vm, IntlDateTimeFormatPro
 
 static EncodedJSValue JSC_HOST_CALL constructIntlDateTimeFormat(ExecState* state)
 {
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     // 12.1.2 Intl.DateTimeFormat ([locales [, options]]) (ECMA-402 2.0)
     // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
     // 2. Let dateTimeFormat be OrdinaryCreateFromConstructor(newTarget, %DateTimeFormatPrototype%).
     // 3. ReturnIfAbrupt(dateTimeFormat).
     Structure* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), jsCast<IntlDateTimeFormatConstructor*>(state->callee())->dateTimeFormatStructure());
-    if (state->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());
-    IntlDateTimeFormat* dateTimeFormat = IntlDateTimeFormat::create(state->vm(), structure);
+    IntlDateTimeFormat* dateTimeFormat = IntlDateTimeFormat::create(vm, structure);
     ASSERT(dateTimeFormat);
 
     // 4. Return InitializeDateTimeFormat(dateTimeFormat, locales, options).
@@ -134,6 +136,8 @@ CallType IntlDateTimeFormatConstructor::getCallData(JSCell*, CallData& callData)
 
 EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatConstructorFuncSupportedLocalesOf(ExecState* state)
 {
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     // 12.2.2 Intl.DateTimeFormat.supportedLocalesOf(locales [, options]) (ECMA-402 2.0)
 
     // 1. Let availableLocales be %DateTimeFormat%.[[availableLocales]].
@@ -142,7 +146,7 @@ EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatConstructorFuncSupportedLocalesOf
 
     // 2. Let requestedLocales be CanonicalizeLocaleList(locales).
     Vector<String> requestedLocales = canonicalizeLocaleList(*state, state->argument(0));
-    if (state->hadException())
+    if (UNLIKELY(scope.exception()))
         return JSValue::encode(jsUndefined());