Changeset 275648 in webkit


Ignore:
Timestamp:
Apr 7, 2021 5:30:15 PM (3 years ago)
Author:
mark.lam@apple.com
Message:

Rename and make the TerminationException a singleton.
https://bugs.webkit.org/show_bug.cgi?id=224295

Reviewed by Keith Miller.

Source/JavaScriptCore:

We previously call it the TerminatedExecutionException, which is a mouthful but
adds no meaningful information. It's now renamed to TerminationException.

We can make it a singleton because the TerminationException is just a VM internal
mechanism for implementing the termination of the current execution stack. It
should never be exposed to user JS code, and therefore, there is no value in
making it a JS object. Making it a singleton simplifies the code.

A TerminationException is now implemented as an Exception cell which holds a
Symbol with the name "TerminationError". The TerminationException is only created
if needed e.g. if the JSC watchdog is created, or if the VM is for a Worker thread
which needs to be able to handle termination requests.

We'll also stop notifying the debugger when we throw the TerminationException.
This is because the TerminationException is not like ordinary exceptions that
should be reported to the debugger. The fact that the TerminationException uses
the exception handling mechanism is just a VM internal implementation detail.
It is not meaningful to report it to the debugger as an exception.

  • API/JSContext.mm:

(-[JSContext evaluateJSScript:]):

  • API/tests/ExecutionTimeLimitTest.cpp:

(testExecutionTimeLimit):

  • bindings/ScriptFunctionCall.cpp:

(Deprecated::ScriptFunctionCall::call):

  • heap/Heap.cpp:

(JSC::Heap::addCoreConstraints):

  • inspector/InjectedScriptManager.cpp:

(Inspector::InjectedScriptManager::injectedScriptFor):

  • inspector/JSGlobalObjectInspectorController.cpp:

(Inspector::JSGlobalObjectInspectorController::reportAPIException):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::unwind):
(JSC::Interpreter::notifyDebuggerOfExceptionToBeThrown):

  • jit/JITOperations.cpp:

(JSC::JSC_DEFINE_JIT_OPERATION):

  • jsc.cpp:

(checkException):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • runtime/ExceptionHelpers.cpp:

(JSC::TerminatedExecutionError::defaultValue): Deleted.
(JSC::createTerminatedExecutionException): Deleted.
(JSC::isTerminatedExecutionException): Deleted.
(JSC::throwTerminatedExecutionException): Deleted.

  • runtime/ExceptionHelpers.h:

(): Deleted.

  • runtime/JSObject.h:

(JSC::JSObject::get const):

  • runtime/JSPromise.cpp:

(JSC::JSPromise::rejectWithCaughtException):

  • runtime/VM.cpp:

(JSC::VM::VM):
(JSC::VM::ensureWatchdog):
(JSC::VM::ensureTerminationException):
(JSC::VM::throwTerminationException):
(JSC::VM::throwException):

  • runtime/VM.h:

(JSC::VM::terminationException const):
(JSC::VM::isTerminationException const):

  • runtime/VMTraps.cpp:

(JSC::VMTraps::handleTraps):

Source/WebCore:

In the WorkerOrWorkletScriptController constructor, we ensure the TerminationException
because workers need to support termination requests.

  • bindings/js/JSDOMExceptionHandling.cpp:

(WebCore::reportException):

  • bindings/js/JSDOMGlobalObject.cpp:

(WebCore::JSC_DEFINE_HOST_FUNCTION):
(WebCore::handleResponseOnStreamingAction):

  • bindings/js/JSDOMPromise.cpp:

(WebCore::DOMPromise::whenPromiseIsSettled):

  • bindings/js/JSDOMPromiseDeferred.cpp:

(WebCore::DeferredPromise::reject):

  • bindings/js/JSEventListener.cpp:

(WebCore::JSEventListener::handleEvent):

  • bindings/js/ReadableStream.cpp:

(WebCore::invokeReadableStreamFunction):
(WebCore::ReadableStream::lock):
(WebCore::checkReadableStream):

  • bindings/js/ReadableStreamDefaultController.cpp:

(WebCore::invokeReadableStreamDefaultControllerFunction):
(WebCore::ReadableStreamDefaultController::error):
(WebCore::ReadableStreamDefaultController::enqueue):

  • workers/WorkerOrWorkletScriptController.cpp:

(WebCore::WorkerOrWorkletScriptController::WorkerOrWorkletScriptController):
(WebCore::WorkerOrWorkletScriptController::evaluate):
(WebCore::WorkerOrWorkletScriptController::linkAndEvaluateModule):
(WebCore::WorkerOrWorkletScriptController::loadAndEvaluateModule):

Location:
trunk/Source
Files:
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSContext.mm

    r273966 r275648  
    11/*
    2  * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    141141        JSValueRef exceptionValue = toRef(apiGlobalObject, scope.exception()->value());
    142142        scope.clearException();
    143         // FIXME: We should not clearException if it is TerminatedExecutionError.
     143        // FIXME: We should not clearException if it is the TerminationException.
    144144        // https://bugs.webkit.org/show_bug.cgi?id=220821
    145145        return [JSValue valueWithNewPromiseRejectedWithReason:[JSValue valueWithJSValueRef:exceptionValue inContext:self] inContext:self];
  • trunk/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp

    r263635 r275648  
    11/*
    2  * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    180180
    181181            if (!exception) {
    182                 printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier);
     182                printf("FAIL: %s TerminationException was not thrown.\n", tierOptions.tier);
    183183                exit(1);
    184184            }
     
    226226           
    227227            if (!exception) {
    228                 printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier);
     228                printf("FAIL: %s TerminationException was not thrown.\n", tierOptions.tier);
    229229                failed = true;
    230230            }
     
    269269           
    270270            if (!exception) {
    271                 printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier);
     271                printf("FAIL: %s TerminationException was not thrown.\n", tierOptions.tier);
    272272                failed = true;
    273273            }
     
    276276        }
    277277
    278         /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */
     278        /* Test the script timeout's TerminationException should NOT be catchable: */
    279279        timeLimit = 100_ms + tierAdjustment;
    280280        JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit.seconds(), shouldTerminateCallback, nullptr);
     
    314314           
    315315            if (exception)
    316                 printf("PASS: %s TerminatedExecutionException was not catchable as expected.\n", tierOptions.tier);
    317             else {
    318                 printf("FAIL: %s TerminatedExecutionException was caught.\n", tierOptions.tier);
     316                printf("PASS: %s TerminationException was not catchable as expected.\n", tierOptions.tier);
     317            else {
     318                printf("FAIL: %s TerminationException was caught.\n", tierOptions.tier);
    319319                failed = true;
    320320            }
     
    361361           
    362362            if (!exception) {
    363                 printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier);
     363                printf("FAIL: %s TerminationException was not thrown.\n", tierOptions.tier);
    364364                failed = true;
    365365            }
     
    406406           
    407407            if (exception) {
    408                 printf("FAIL: %s Unexpected TerminatedExecutionException thrown.\n", tierOptions.tier);
     408                printf("FAIL: %s Unexpected TerminationException thrown.\n", tierOptions.tier);
    409409                failed = true;
    410410            }
     
    455455               
    456456                if (!exception)
    457                     printf("FAIL: %s TerminatedExecutionException was not thrown during timeout extension test.\n", tierOptions.tier);
     457                    printf("FAIL: %s TerminationException was not thrown during timeout extension test.\n", tierOptions.tier);
    458458               
    459459                failed = true;
  • trunk/Source/JavaScriptCore/ChangeLog

    r275626 r275648  
     12021-04-07  Mark Lam  <mark.lam@apple.com>
     2
     3        Rename and make the TerminationException a singleton.
     4        https://bugs.webkit.org/show_bug.cgi?id=224295
     5
     6        Reviewed by Keith Miller.
     7
     8        We previously call it the TerminatedExecutionException, which is a mouthful but
     9        adds no meaningful information.  It's now renamed to TerminationException.
     10
     11        We can make it a singleton because the TerminationException is just a VM internal
     12        mechanism for implementing the termination of the current execution stack.  It
     13        should never be exposed to user JS code, and therefore, there is no value in
     14        making it a JS object.  Making it a singleton simplifies the code.
     15
     16        A TerminationException is now implemented as an Exception cell which holds a
     17        Symbol with the name "TerminationError".  The TerminationException is only created
     18        if needed e.g. if the JSC watchdog is created, or if the VM is for a Worker thread
     19        which needs to be able to handle termination requests.
     20
     21        We'll also stop notifying the debugger when we throw the TerminationException.
     22        This is because the TerminationException is not like ordinary exceptions that
     23        should be reported to the debugger. The fact that the TerminationException uses
     24        the exception handling mechanism is just a VM internal implementation detail.
     25        It is not meaningful to report it to the debugger as an exception.
     26
     27        * API/JSContext.mm:
     28        (-[JSContext evaluateJSScript:]):
     29        * API/tests/ExecutionTimeLimitTest.cpp:
     30        (testExecutionTimeLimit):
     31        * bindings/ScriptFunctionCall.cpp:
     32        (Deprecated::ScriptFunctionCall::call):
     33        * heap/Heap.cpp:
     34        (JSC::Heap::addCoreConstraints):
     35        * inspector/InjectedScriptManager.cpp:
     36        (Inspector::InjectedScriptManager::injectedScriptFor):
     37        * inspector/JSGlobalObjectInspectorController.cpp:
     38        (Inspector::JSGlobalObjectInspectorController::reportAPIException):
     39        * interpreter/Interpreter.cpp:
     40        (JSC::Interpreter::unwind):
     41        (JSC::Interpreter::notifyDebuggerOfExceptionToBeThrown):
     42        * jit/JITOperations.cpp:
     43        (JSC::JSC_DEFINE_JIT_OPERATION):
     44        * jsc.cpp:
     45        (checkException):
     46        * llint/LLIntSlowPaths.cpp:
     47        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     48        * runtime/ExceptionHelpers.cpp:
     49        (JSC::TerminatedExecutionError::defaultValue): Deleted.
     50        (JSC::createTerminatedExecutionException): Deleted.
     51        (JSC::isTerminatedExecutionException): Deleted.
     52        (JSC::throwTerminatedExecutionException): Deleted.
     53        * runtime/ExceptionHelpers.h:
     54        (): Deleted.
     55        * runtime/JSObject.h:
     56        (JSC::JSObject::get const):
     57        * runtime/JSPromise.cpp:
     58        (JSC::JSPromise::rejectWithCaughtException):
     59        * runtime/VM.cpp:
     60        (JSC::VM::VM):
     61        (JSC::VM::ensureWatchdog):
     62        (JSC::VM::ensureTerminationException):
     63        (JSC::VM::throwTerminationException):
     64        (JSC::VM::throwException):
     65        * runtime/VM.h:
     66        (JSC::VM::terminationException const):
     67        (JSC::VM::isTerminationException const):
     68        * runtime/VMTraps.cpp:
     69        (JSC::VMTraps::handleTraps):
     70
    1712021-04-07  Yusuke Suzuki  <ysuzuki@apple.com>
    272
  • trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp

    r261895 r275648  
    11/*
    2  * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 * Copyright (C) 2009 Google Inc. All rights reserved.
    44 *
     
    128128    if (exception) {
    129129        // Do not treat a terminated execution exception as having an exception. Just treat it as an empty result.
    130         if (!isTerminatedExecutionException(vm, exception))
     130        if (!vm.isTerminationException(exception))
    131131            return makeUnexpected(exception);
    132132        return { };
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r275261 r275648  
    28182818                visitor.appendUnbarriered(m_vm.exception());
    28192819                visitor.appendUnbarriered(m_vm.lastException());
     2820
     2821                // We're going to m_terminationException directly instead of going through
     2822                // the exception() getter because we want to assert in the getter that the
     2823                // TerminationException has been reified. Here, we don't care if it is
     2824                // reified or not.
     2825                visitor.appendUnbarriered(m_vm.m_terminationException);
    28202826            }
    28212827        })),
  • trunk/Source/JavaScriptCore/inspector/InjectedScriptManager.cpp

    r266885 r275648  
    11/*
    2  * Copyright (C) 2007-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2007-2021 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
    44 * Copyright (C) 2012 Google Inc. All rights reserved.
     
    189189        ASSERT(error);
    190190
    191         if (isTerminatedExecutionException(globalObject->vm(), error))
     191        if (globalObject->vm().isTerminationException(error))
    192192            return InjectedScript();
    193193
  • trunk/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.cpp

    r266885 r275648  
    11/*
    2  * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    173173{
    174174    VM& vm = globalObject->vm();
    175     if (isTerminatedExecutionException(vm, exception))
     175    if (vm.isTerminationException(exception))
    176176        return;
    177177
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r274239 r275648  
    11/*
    2  * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008-2021 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
    44 *
     
    608608    // Calculate an exception handler vPC, unwinding call frames as necessary.
    609609    HandlerInfo* handler = nullptr;
    610     UnwindFunctor functor(vm, callFrame, isTerminatedExecutionException(vm, exception), codeBlock, handler);
     610    UnwindFunctor functor(vm, callFrame, vm.isTerminationException(exception), codeBlock, handler);
    611611    StackVisitor::visit<StackVisitor::TerminateIfTopEntryFrameIsEmpty>(callFrame, vm, functor);
    612612    if (vm.hasCheckpointOSRSideState())
     
    621621void Interpreter::notifyDebuggerOfExceptionToBeThrown(VM& vm, JSGlobalObject* globalObject, CallFrame* callFrame, Exception* exception)
    622622{
     623    ASSERT(!vm.isTerminationException(exception));
     624
    623625    Debugger* debugger = globalObject->debugger();
    624626    if (debugger && debugger->needsExceptionCallbacks() && !exception->didNotifyInspectorOfThrow()) {
     
    628630        // https://bugs.webkit.org/show_bug.cgi?id=121754
    629631
    630         bool hasCatchHandler;
    631         bool isTermination = isTerminatedExecutionException(vm, exception);
    632         if (isTermination)
    633             hasCatchHandler = false;
    634         else {
    635             GetCatchHandlerFunctor functor;
    636             StackVisitor::visit(callFrame, vm, functor);
    637             HandlerInfo* handler = functor.handler();
    638             ASSERT(!handler || handler->isCatchHandler());
    639             hasCatchHandler = !!handler;
    640         }
     632        GetCatchHandlerFunctor functor;
     633        StackVisitor::visit(callFrame, vm, functor);
     634        HandlerInfo* handler = functor.handler();
     635        ASSERT(!handler || handler->isCatchHandler());
     636        bool hasCatchHandler = !!handler;
    641637
    642638        debugger->exception(globalObject, callFrame, exception->value(), hasCatchHandler);
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r272580 r275648  
    35203520    RELEASE_ASSERT(!!scope.exception());
    35213521
    3522     if (isTerminatedExecutionException(vm, scope.exception())) {
     3522    if (vm.isTerminationException(scope.exception())) {
    35233523        genericUnwind(vm, callFrame);
    35243524        return 1;
  • trunk/Source/JavaScriptCore/jsc.cpp

    r275247 r275648  
    29412941    VM& vm = globalObject->vm();
    29422942
    2943     if (options.m_treatWatchdogExceptionAsSuccess && value.inherits<TerminatedExecutionError>(vm)) {
     2943    auto isTerminationException = [&] (JSValue value) {
     2944        if (!value.isCell())
     2945            return false;
     2946
     2947        JSCell* valueCell = value.asCell();
     2948        vm.ensureTerminationException();
     2949        Exception* terminationException = vm.terminationException();
     2950        Exception* exception = jsDynamicCast<Exception*>(vm, valueCell);
     2951        if (exception)
     2952            return vm.isTerminationException(exception);
     2953        JSCell* terminationError = terminationException->value().asCell();
     2954        return valueCell == terminationError;
     2955    };
     2956
     2957    if (options.m_treatWatchdogExceptionAsSuccess && isTerminationException(value)) {
    29442958        ASSERT(hasException);
    29452959        return;
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r272580 r275648  
    11/*
    2  * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    21892189    RELEASE_ASSERT(!!throwScope.exception());
    21902190
    2191     if (isTerminatedExecutionException(vm, throwScope.exception()))
     2191    if (vm.isTerminationException(throwScope.exception()))
    21922192        LLINT_RETURN_TWO(pc, bitwise_cast<void*>(static_cast<uintptr_t>(1)));
    21932193    LLINT_RETURN_TWO(pc, nullptr);
  • trunk/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp

    r275439 r275648  
    4040namespace JSC {
    4141
    42 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(TerminatedExecutionError);
    43 
    44 const ClassInfo TerminatedExecutionError::s_info = { "TerminatedExecutionError", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(TerminatedExecutionError) };
    45 
    46 JSValue TerminatedExecutionError::defaultValue(const JSObject*, JSGlobalObject* globalObject, PreferredPrimitiveType hint)
    47 {
    48     if (hint == PreferString)
    49         return jsNontrivialString(globalObject->vm(), String("JavaScript execution terminated."_s));
    50     return JSValue(PNaN);
    51 }
    52 
    53 JSObject* createTerminatedExecutionException(VM* vm)
    54 {
    55     return TerminatedExecutionError::create(*vm);
    56 }
    57 
    58 bool isTerminatedExecutionException(VM& vm, Exception* exception)
    59 {
    60     if (!exception->value().isObject())
    61         return false;
    62 
    63     return exception->value().inherits<TerminatedExecutionError>(vm);
    64 }
    65 
    6642JSObject* createStackOverflowError(JSGlobalObject* globalObject)
    6743{
     
    386362}
    387363
    388 Exception* throwTerminatedExecutionException(JSGlobalObject* globalObject, ThrowScope& scope)
    389 {
    390     VM& vm = globalObject->vm();
    391     ErrorHandlingScope errorScope(vm);
    392     return throwException(globalObject, scope, createTerminatedExecutionException(&vm));
    393 }
    394 
    395364} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/ExceptionHelpers.h

    r275439 r275648  
    11/*
    2  * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4040String defaultSourceAppender(const String&, const String&, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred);
    4141
    42 JSObject* createTerminatedExecutionException(VM*);
    43 JS_EXPORT_PRIVATE bool isTerminatedExecutionException(VM&, Exception*);
    4442JS_EXPORT_PRIVATE JSObject* createError(JSGlobalObject*, JSValue, const String&, ErrorInstance::SourceAppender);
    4543JS_EXPORT_PRIVATE JSObject* createStackOverflowError(JSGlobalObject*);
     
    6260JS_EXPORT_PRIVATE Exception* throwOutOfMemoryError(JSGlobalObject*, ThrowScope&, const String&);
    6361JS_EXPORT_PRIVATE Exception* throwStackOverflowError(JSGlobalObject*, ThrowScope&);
    64 JS_EXPORT_PRIVATE Exception* throwTerminatedExecutionException(JSGlobalObject*, ThrowScope&);
    65 
    66 
    67 class TerminatedExecutionError final : public JSNonFinalObject {
    68 public:
    69     using Base = JSNonFinalObject;
    70     static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
    71 
    72     template<typename CellType, SubspaceAccess>
    73     static IsoSubspace* subspaceFor(VM& vm)
    74     {
    75         STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(TerminatedExecutionError, Base);
    76         return &vm.plainObjectSpace;
    77     }
    78 
    79     static TerminatedExecutionError* create(VM& vm)
    80     {
    81         TerminatedExecutionError* error = new (NotNull, allocateCell<TerminatedExecutionError>(vm.heap)) TerminatedExecutionError(vm);
    82         error->finishCreation(vm);
    83         return error;
    84     }
    85 
    86     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    87     {
    88         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
    89     }
    90 
    91     DECLARE_EXPORT_INFO;
    92 
    93 private:
    94     explicit TerminatedExecutionError(VM& vm)
    95         : JSNonFinalObject(vm, vm.terminatedExecutionErrorStructure.get())
    96     {
    97     }
    98 
    99     static JSValue defaultValue(const JSObject*, JSGlobalObject*, PreferredPrimitiveType);
    100 
    101 };
    10262
    10363} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r275363 r275648  
    7474struct HashTableValue;
    7575
    76 JS_EXPORT_PRIVATE bool isTerminatedExecutionException(VM&, Exception*);
    7776JS_EXPORT_PRIVATE Exception* throwTypeError(JSGlobalObject*, ThrowScope&, const String&);
    7877extern JS_EXPORT_PRIVATE const ASCIILiteral NonExtensibleObjectPropertyDefineError;
     
    14981497    bool hasProperty = const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
    14991498
    1500     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(vm, scope.exception()) || !hasProperty);
     1499    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()) || !hasProperty);
    15011500    RETURN_IF_EXCEPTION(scope, jsUndefined());
    15021501
     
    15141513    bool hasProperty = const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
    15151514
    1516     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(vm, scope.exception()) || !hasProperty);
     1515    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()) || !hasProperty);
    15171516    RETURN_IF_EXCEPTION(scope, jsUndefined());
    15181517
  • trunk/Source/JavaScriptCore/runtime/JSPromise.cpp

    r273138 r275648  
    229229    Exception* exception = scope.exception();
    230230    ASSERT(exception);
    231     if (UNLIKELY(isTerminatedExecutionException(vm, exception))) {
     231    if (UNLIKELY(vm.isTerminationException(exception))) {
    232232        scope.release();
    233233        return this;
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r275490 r275648  
    433433
    434434    propertyNames = new CommonIdentifiers(*this);
    435     terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, nullptr, jsNull()));
    436435    propertyNameEnumeratorStructure.set(*this, JSPropertyNameEnumerator::createStructure(*this, nullptr, jsNull()));
    437436    getterSetterStructure.set(*this, GetterSetter::createStructure(*this, nullptr, jsNull()));
     
    742741Watchdog& VM::ensureWatchdog()
    743742{
    744     if (!m_watchdog)
     743    if (!m_watchdog) {
    745744        m_watchdog = adoptRef(new Watchdog(this));
     745        ensureTerminationException();
     746    }
    746747    return *m_watchdog;
    747748}
     
    762763}
    763764#endif // ENABLE(SAMPLING_PROFILER)
     765
     766static SymbolImpl::StaticSymbolImpl terminationErrorSymbol { "TerminationError", SymbolImpl::s_flagIsPrivate };
     767
     768Exception* VM::ensureTerminationException()
     769{
     770    if (!m_terminationException) {
     771        Symbol* terminationError = Symbol::create(*this, terminationErrorSymbol);
     772        m_terminationException = Exception::create(*this, terminationError, Exception::DoNotCaptureStack);
     773    }
     774    return m_terminationException;
     775}
    764776
    765777#if ENABLE(JIT)
     
    947959}
    948960
    949 Exception* VM::throwException(JSGlobalObject* globalObject, Exception* exception)
    950 {
     961void VM::throwTerminationException()
     962{
     963    setException(terminationException());
     964}
     965
     966Exception* VM::throwException(JSGlobalObject* globalObject, Exception* exceptionToThrow)
     967{
     968    // The TerminationException is not like ordinary exceptions that should be
     969    // reported to the debugger. The fact that the TerminationException uses the
     970    // exception handling mechanism is just a VM internal implementation detail.
     971    // It is not meaningful to report it to the debugger as an exception.
     972    if (isTerminationException(exceptionToThrow)) {
     973        // Note: we can only get here is we're just re-throwing the TerminationException
     974        // from C++ functions to propagate it. If we're throwing it for the first
     975        // time, we would have gone through VM::throwTerminationException().
     976        setException(exceptionToThrow);
     977        return exceptionToThrow;
     978    }
     979
    951980    CallFrame* throwOriginFrame = topJSCallFrame();
    952981    if (!throwOriginFrame)
     
    959988    }
    960989
    961     interpreter->notifyDebuggerOfExceptionToBeThrown(*this, globalObject, throwOriginFrame, exception);
    962 
    963     setException(exception);
     990    interpreter->notifyDebuggerOfExceptionToBeThrown(*this, globalObject, throwOriginFrame, exceptionToThrow);
     991
     992    setException(exceptionToThrow);
    964993
    965994#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
     
    967996    m_throwingThread = &Thread::current();
    968997#endif
    969     return exception;
     998    return exceptionToThrow;
    970999}
    9711000
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r274817 r275648  
    338338    WeakRandom& random() { return m_random; }
    339339    Integrity::Random& integrityRandom() { return m_integrityRandom; }
     340
     341    JS_EXPORT_PRIVATE Exception* ensureTerminationException();
     342    Exception* terminationException() const
     343    {
     344        ASSERT(m_terminationException);
     345        return m_terminationException;
     346    }
     347    bool isTerminationException(Exception* exception) const
     348    {
     349        ASSERT(exception);
     350        return exception == m_terminationException;
     351    }
     352
     353    void throwTerminationException();
    340354
    341355private:
     
    665679    Strong<Structure> structureStructure;
    666680    Strong<Structure> structureRareDataStructure;
    667     Strong<Structure> terminatedExecutionErrorStructure;
    668681    Strong<Structure> stringStructure;
    669682    Strong<Structure> propertyNameEnumeratorStructure;
     
    10791092    void* needTrapHandlingAddress() { return m_traps.needTrapHandlingAddress(); }
    10801093
     1094    // These may be called concurrently from another thread.
    10811095    void notifyNeedDebuggerBreak() { m_traps.fireTrap(VMTraps::NeedDebuggerBreak); }
    10821096    void notifyNeedShellTimeoutCheck() { m_traps.fireTrap(VMTraps::NeedShellTimeoutCheck); }
     
    11871201
    11881202    Exception* m_exception { nullptr };
     1203    Exception* m_terminationException { nullptr };
    11891204    Exception* m_lastException { nullptr };
    11901205#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
  • trunk/Source/JavaScriptCore/runtime/VMTraps.cpp

    r272823 r275648  
    11/*
    2  * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    381381
    382382        case NeedTermination:
    383             throwException(globalObject, scope, createTerminatedExecutionException(&vm));
    384             return;
     383            RELEASE_AND_RETURN(scope, vm.throwTerminationException());
    385384
    386385        default:
  • trunk/Source/WebCore/ChangeLog

    r275641 r275648  
     12021-04-07  Mark Lam  <mark.lam@apple.com>
     2
     3        Rename and make the TerminationException a singleton.
     4        https://bugs.webkit.org/show_bug.cgi?id=224295
     5
     6        Reviewed by Keith Miller.
     7
     8        In the WorkerOrWorkletScriptController constructor, we ensure the TerminationException
     9        because workers need to support termination requests.
     10
     11        * bindings/js/JSDOMExceptionHandling.cpp:
     12        (WebCore::reportException):
     13        * bindings/js/JSDOMGlobalObject.cpp:
     14        (WebCore::JSC_DEFINE_HOST_FUNCTION):
     15        (WebCore::handleResponseOnStreamingAction):
     16        * bindings/js/JSDOMPromise.cpp:
     17        (WebCore::DOMPromise::whenPromiseIsSettled):
     18        * bindings/js/JSDOMPromiseDeferred.cpp:
     19        (WebCore::DeferredPromise::reject):
     20        * bindings/js/JSEventListener.cpp:
     21        (WebCore::JSEventListener::handleEvent):
     22        * bindings/js/ReadableStream.cpp:
     23        (WebCore::invokeReadableStreamFunction):
     24        (WebCore::ReadableStream::lock):
     25        (WebCore::checkReadableStream):
     26        * bindings/js/ReadableStreamDefaultController.cpp:
     27        (WebCore::invokeReadableStreamDefaultControllerFunction):
     28        (WebCore::ReadableStreamDefaultController::error):
     29        (WebCore::ReadableStreamDefaultController::enqueue):
     30        * workers/WorkerOrWorkletScriptController.cpp:
     31        (WebCore::WorkerOrWorkletScriptController::WorkerOrWorkletScriptController):
     32        (WebCore::WorkerOrWorkletScriptController::evaluate):
     33        (WebCore::WorkerOrWorkletScriptController::linkAndEvaluateModule):
     34        (WebCore::WorkerOrWorkletScriptController::loadAndEvaluateModule):
     35
    1362021-04-07  Simon Fraser  <simon.fraser@apple.com>
    237
  • trunk/Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp

    r274770 r275648  
    11/*
    22 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2004-2020 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2004-2021 Apple Inc. All rights reserved.
    44 *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
    55 *  Copyright (C) 2013 Michael Pruett <michael@68k.org>
     
    9595
    9696    RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
    97     if (isTerminatedExecutionException(vm, exception))
     97    if (vm.isTerminationException(exception))
    9898        return;
    9999
  • trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp

    r275212 r275648  
    142142    auto value = createDOMException(globalObject, code, message);
    143143
    144     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(vm, scope.exception()));
     144    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()));
    145145
    146146    return JSValue::encode(value);
     
    411411                auto error = createDOMException(*globalObject, WTFMove(exception));
    412412                if (UNLIKELY(scope.exception())) {
    413                     ASSERT(isTerminatedExecutionException(vm, scope.exception()));
     413                    ASSERT(vm.isTerminationException(scope.exception()));
    414414                    compiler->cancel();
    415415                    return;
  • trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp

    r264838 r275648  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5858    auto thenFunction = promise->get(&lexicalGlobalObject, privateName);
    5959
    60     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     60    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()));
    6161    if (scope.exception())
    6262        return IsCallbackRegistered::No;
     
    7272    call(&lexicalGlobalObject, thenFunction, callData, promise, arguments);
    7373
    74     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     74    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()));
    7575    return scope.exception() ? IsCallbackRegistered::No : IsCallbackRegistered::Yes;
    7676}
  • trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp

    r274832 r275648  
    11/*
    2  * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    130130    ASSERT(m_globalObject);
    131131    auto& lexicalGlobalObject = *m_globalObject;
    132     JSC::JSLockHolder locker(&lexicalGlobalObject);
     132    JSC::VM& vm = lexicalGlobalObject.vm();
     133    JSC::JSLockHolder locker(vm);
    133134
    134135    if (exception.code() == ExistingExceptionError) {
     
    144145    }
    145146
    146     auto scope = DECLARE_THROW_SCOPE(lexicalGlobalObject.vm());
     147    auto scope = DECLARE_THROW_SCOPE(vm);
    147148    auto error = createDOMException(lexicalGlobalObject, WTFMove(exception));
    148149    if (UNLIKELY(scope.exception())) {
    149         ASSERT(isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     150        ASSERT(vm.isTerminationException(scope.exception()));
    150151        return;
    151152    }
     
    163164    ASSERT(m_globalObject);
    164165    auto& lexicalGlobalObject = *m_globalObject;
    165     JSC::JSLockHolder locker(&lexicalGlobalObject);
     166    JSC::VM& vm = lexicalGlobalObject.vm();
     167    JSC::JSLockHolder locker(vm);
    166168
    167169    if (ec == ExistingExceptionError) {
    168         auto scope = DECLARE_CATCH_SCOPE(lexicalGlobalObject.vm());
     170        auto scope = DECLARE_CATCH_SCOPE(vm);
    169171
    170172        EXCEPTION_ASSERT(scope.exception());
     
    177179    }
    178180
    179     auto scope = DECLARE_THROW_SCOPE(lexicalGlobalObject.vm());
     181    auto scope = DECLARE_THROW_SCOPE(vm);
    180182    auto error = createDOMException(&lexicalGlobalObject, ec, message);
    181183    if (UNLIKELY(scope.exception())) {
    182         ASSERT(isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     184        ASSERT(vm.isTerminationException(scope.exception()));
    183185        return;
    184186    }
  • trunk/Source/WebCore/bindings/js/JSEventListener.cpp

    r274996 r275648  
    194194        if (is<WorkerGlobalScope>(scriptExecutionContext)) {
    195195            auto& scriptController = *downcast<WorkerGlobalScope>(scriptExecutionContext).script();
    196             bool terminatorCausedException = (scope.exception() && isTerminatedExecutionException(vm, scope.exception()));
     196            bool terminatorCausedException = (scope.exception() && vm.isTerminationException(scope.exception()));
    197197            if (terminatorCausedException || scriptController.isTerminatingExecution())
    198198                scriptController.forbidExecution();
  • trunk/Source/WebCore/bindings/js/ReadableStream.cpp

    r272166 r275648  
    11/*
    2  * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    6868
    6969    auto function = lexicalGlobalObject.get(&lexicalGlobalObject, identifier);
    70     ASSERT(function.isCallable(lexicalGlobalObject.vm()));
     70    ASSERT(function.isCallable(vm));
    7171
    7272    auto scope = DECLARE_CATCH_SCOPE(vm);
    7373    auto callData = JSC::getCallData(vm, function);
    7474    auto result = call(&lexicalGlobalObject, function, callData, thisValue, arguments);
    75     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     75    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()));
    7676    if (scope.exception())
    7777        return { };
     
    132132
    133133    JSC::construct(&lexicalGlobalObject, constructor, constructData, args);
    134     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     134    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()));
    135135}
    136136
     
    150150
    151151    auto result = call(&lexicalGlobalObject, function, callData, JSC::jsUndefined(), arguments);
    152     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     152    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()));
    153153
    154154    return result.isTrue() || scope.exception();
  • trunk/Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp

    r270107 r275648  
    11/*
    22 * Copyright (C) 2016 Canon Inc.
    3  * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
     3 * Copyright (C) 2016-2021 Apple Inc. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    5151    auto callData = JSC::getCallData(vm, function);
    5252    call(&lexicalGlobalObject, function, callData, JSC::jsUndefined(), arguments);
    53     EXCEPTION_ASSERT(!scope.exception() || isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     53    EXCEPTION_ASSERT(!scope.exception() || vm.isTerminationException(scope.exception()));
    5454    return !scope.exception();
    5555}
     
    7676
    7777    if (UNLIKELY(scope.exception())) {
    78         ASSERT(isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     78        ASSERT(vm.isTerminationException(scope.exception()));
    7979        return;
    8080    }
     
    8484    arguments.append(value);
    8585
    86     auto* clientData = static_cast<JSVMClientData*>(lexicalGlobalObject.vm().clientData);
     86    auto* clientData = static_cast<JSVMClientData*>(vm.clientData);
    8787    auto& privateName = clientData->builtinFunctions().readableStreamInternalsBuiltins().readableStreamDefaultControllerErrorPrivateName();
    8888
     
    122122
    123123    if (UNLIKELY(scope.exception())) {
    124         ASSERT(isTerminatedExecutionException(lexicalGlobalObject.vm(), scope.exception()));
     124        ASSERT(vm.isTerminationException(scope.exception()));
    125125        return false;
    126126    }
  • trunk/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp

    r273777 r275648  
    11/*
    2  * Copyright (C) 2008-2020 Apple Inc. All Rights Reserved.
     2 * Copyright (C) 2008-2021 Apple Inc. All Rights Reserved.
    33 * Copyright (C) 2011, 2012 Google Inc. All Rights Reserved.
    44 *
     
    6868{
    6969    m_vm->heap.acquireAccess(); // It's not clear that we have good discipline for heap access, so turn it on permanently.
     70    {
     71        JSLockHolder lock(m_vm.get());
     72        m_vm->ensureTerminationException();
     73    }
     74
    7075    JSVMClientData::initNormalWorld(m_vm.get(), type);
    7176}
     
    219224    JSExecState::profiledEvaluate(&globalObject, JSC::ProfilingReason::Other, sourceCode.jsSourceCode(), m_globalScopeWrapper->globalThis(), returnedException);
    220225
    221     if ((returnedException && isTerminatedExecutionException(vm, returnedException)) || isTerminatingExecution()) {
     226    if ((returnedException && vm.isTerminationException(returnedException)) || isTerminatingExecution()) {
    222227        forbidExecution();
    223228        return;
     
    352357    NakedPtr<JSC::Exception> returnedException;
    353358    JSExecState::linkAndEvaluateModule(globalObject, Identifier::fromUid(vm, scriptFetcher.moduleKey()), jsUndefined(), returnedException);
    354     if ((returnedException && isTerminatedExecutionException(vm, returnedException)) || isTerminatingExecution()) {
     359    if ((returnedException && vm.isTerminationException(returnedException)) || isTerminatingExecution()) {
    355360        forbidExecution();
    356361        return;
     
    410415            NakedPtr<JSC::Exception> returnedException;
    411416            JSExecState::linkAndEvaluateModule(*globalObject, moduleKey, jsUndefined(), returnedException);
    412             if ((returnedException && isTerminatedExecutionException(vm, returnedException)) || context->script()->isTerminatingExecution()) {
     417            if ((returnedException && vm.isTerminationException(returnedException)) || context->script()->isTerminatingExecution()) {
    413418                if (context->script())
    414419                    context->script()->forbidExecution();
Note: See TracChangeset for help on using the changeset viewer.