⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 290788 in webkit


Ignore:
Timestamp:
Mar 3, 2022, 11:51:30 AM (4 years ago)
Author:
sbarati@apple.com
Message:

Add a DeferTraps scope
https://bugs.webkit.org/show_bug.cgi?id=237306
<rdar://83494949>

Reviewed by Mark Lam.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::jettison):
(JSC::CodeBlock::noticeIncomingCall):

  • bytecode/CodeBlock.h:
  • bytecode/RepatchInlines.h:

(JSC::linkFor):
(JSC::virtualForWithFunction):

  • dfg/DFGOperations.cpp:

(JSC::DFG::JSC_DEFINE_JIT_OPERATION):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::executeProgram):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeModuleProgram):

  • interpreter/InterpreterInlines.h:

(JSC::Interpreter::execute):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::setUpCall):

  • runtime/ExceptionScope.h:
  • runtime/ScriptExecutable.cpp:

(JSC::ScriptExecutable::installCode):

  • runtime/VMTraps.cpp:

(JSC::VMTraps::handleTraps):
(JSC::VMTraps::takeTopPriorityTrap):

  • runtime/VMTraps.h:

(JSC::VMTraps::needHandling const):
(JSC::VMTraps::maybeNeedHandling const):
(JSC::VMTraps::hasTrapBit):
(JSC::VMTraps::setTrapBit):

  • runtime/VMTrapsInlines.h:

(JSC::DeferTraps::DeferTraps):
(JSC::DeferTraps::~DeferTraps):

Location:
trunk/Source/JavaScriptCore
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r290775 r290788  
     12022-03-03  Saam Barati  <sbarati@apple.com>
     2
     3        Add a DeferTraps scope
     4        https://bugs.webkit.org/show_bug.cgi?id=237306
     5        <rdar://83494949>
     6
     7        Reviewed by Mark Lam.
     8
     9        * bytecode/CodeBlock.cpp:
     10        (JSC::CodeBlock::CodeBlock):
     11        (JSC::CodeBlock::jettison):
     12        (JSC::CodeBlock::noticeIncomingCall):
     13        * bytecode/CodeBlock.h:
     14        * bytecode/RepatchInlines.h:
     15        (JSC::linkFor):
     16        (JSC::virtualForWithFunction):
     17        * dfg/DFGOperations.cpp:
     18        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
     19        * interpreter/Interpreter.cpp:
     20        (JSC::Interpreter::executeProgram):
     21        (JSC::Interpreter::executeCall):
     22        (JSC::Interpreter::executeConstruct):
     23        (JSC::Interpreter::execute):
     24        (JSC::Interpreter::executeModuleProgram):
     25        * interpreter/InterpreterInlines.h:
     26        (JSC::Interpreter::execute):
     27        * llint/LLIntSlowPaths.cpp:
     28        (JSC::LLInt::setUpCall):
     29        * runtime/ExceptionScope.h:
     30        * runtime/ScriptExecutable.cpp:
     31        (JSC::ScriptExecutable::installCode):
     32        * runtime/VMTraps.cpp:
     33        (JSC::VMTraps::handleTraps):
     34        (JSC::VMTraps::takeTopPriorityTrap):
     35        * runtime/VMTraps.h:
     36        (JSC::VMTraps::needHandling const):
     37        (JSC::VMTraps::maybeNeedHandling const):
     38        (JSC::VMTraps::hasTrapBit):
     39        (JSC::VMTraps::setTrapBit):
     40        * runtime/VMTrapsInlines.h:
     41        (JSC::DeferTraps::DeferTraps):
     42        (JSC::DeferTraps::~DeferTraps):
     43
    1442022-03-03  Adrian Perez de Castro  <aperez@igalia.com>
    245
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r290769 r290788  
    280280    , m_didFailFTLCompilation(false)
    281281    , m_hasBeenCompiledWithFTL(false)
     282    , m_isJettisoned(false)
    282283    , m_numCalleeLocals(other.m_numCalleeLocals)
    283284    , m_numVars(other.m_numVars)
     
    331332    , m_didFailFTLCompilation(false)
    332333    , m_hasBeenCompiledWithFTL(false)
     334    , m_isJettisoned(false)
    333335    , m_numCalleeLocals(unlinkedCodeBlock->numCalleeLocals())
    334336    , m_numVars(unlinkedCodeBlock->numVars())
     
    21922194    VM& vm = *m_vm;
    21932195
     2196    m_isJettisoned = true;
     2197
    21942198    CodeBlock* codeBlock = this; // Placate GCC for use in CODEBLOCK_LOG_EVENT  (does not like this).
    21952199    CODEBLOCK_LOG_EVENT(codeBlock, "jettison", ("due to ", reason, ", counting = ", mode == CountReoptimization, ", detail = ", pointerDump(detail)));
     
    23582362void CodeBlock::noticeIncomingCall(CallFrame* callerFrame)
    23592363{
     2364    RELEASE_ASSERT(!m_isJettisoned);
     2365
    23602366    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
    23612367   
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r290769 r290788  
    775775    bool m_didFailFTLCompilation : 1;
    776776    bool m_hasBeenCompiledWithFTL : 1;
     777    bool m_isJettisoned : 1;
    777778
    778779    bool m_visitChildrenSkippedDueToOldAge { false };
  • trunk/Source/JavaScriptCore/bytecode/RepatchInlines.h

    r290769 r290788  
    2828#include "Repatch.h"
    2929
     30#include "VMTrapsInlines.h"
     31
    3032namespace JSC {
    3133
     
    125127    MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
    126128    CodeBlock* codeBlock = nullptr;
     129
     130    DeferTraps deferTraps(vm); // We can't jettison any code until after we link the call.
     131
    127132    if (executable->isHostFunction()) {
    128133        codePtr = jsToWasmICCodePtr(vm, kind, callee);
     
    188193    JSScope* scope = function->scopeUnchecked();
    189194    ExecutableBase* executable = function->executable();
     195
     196    DeferTraps deferTraps(vm); // We can't jettison if we're going to call this CodeBlock.
     197
    190198    if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
    191199        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r290769 r290788  
    7979#include "TypeProfilerLog.h"
    8080#include "VMInlines.h"
     81#include "VMTrapsInlines.h"
    8182
    8283#if ENABLE(JIT)
     
    37133714    MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
    37143715    CodeBlock* codeBlock = nullptr;
     3716    DeferTraps deferTraps(vm); // We can't jettison this code if we're about to link to it.
     3717
    37153718    if (executable->isHostFunction())
    37163719        codePtr = executable->entrypointFor(kind, MustCheckArity);
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r290769 r290788  
    950950        scope->flattenDictionaryObject(vm);
    951951
    952     ProgramCodeBlock* codeBlock;
    953     {
    954         CodeBlock* tempCodeBlock;
    955         program->prepareForExecution<ProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
    956         RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
    957 
    958         codeBlock = jsCast<ProgramCodeBlock*>(tempCodeBlock);
    959         ASSERT(codeBlock && codeBlock->numParameters() == 1); // 1 parameter for 'this'.
    960     }
    961 
    962952    RefPtr<JITCode> jitCode;
    963953    ProtoCallFrame protoCallFrame;
    964954    {
    965         DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
    966         jitCode = program->generatedJITCode();
    967         protoCallFrame.init(codeBlock, globalObject, globalCallee, thisObj, 1);
     955        DeferTraps deferTraps(vm); // We can't jettison this code if we're about to run it.
     956
     957        ProgramCodeBlock* codeBlock;
     958        {
     959            CodeBlock* tempCodeBlock;
     960            program->prepareForExecution<ProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
     961            RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
     962
     963            codeBlock = jsCast<ProgramCodeBlock*>(tempCodeBlock);
     964            ASSERT(codeBlock && codeBlock->numParameters() == 1); // 1 parameter for 'this'.
     965        }
     966
     967        {
     968            DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
     969            jitCode = program->generatedJITCode();
     970            protoCallFrame.init(codeBlock, globalObject, globalCallee, thisObj, 1);
     971        }
    968972    }
    969973
     
    10121016    }
    10131017
    1014     CodeBlock* newCodeBlock = nullptr;
    1015     if (isJSCall) {
    1016         // Compile the callee:
    1017         callData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(function), scope, CodeForCall, newCodeBlock);
    1018         RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
    1019 
    1020         ASSERT(newCodeBlock);
    1021         newCodeBlock->m_shouldAlwaysBeInlined = false;
    1022     }
    1023 
    10241018    RefPtr<JITCode> jitCode;
    10251019    ProtoCallFrame protoCallFrame;
    10261020    {
    1027         DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
    1028         if (isJSCall)
    1029             jitCode = callData.js.functionExecutable->generatedJITCodeForCall();
    1030         protoCallFrame.init(newCodeBlock, globalObject, function, thisValue, argsCount, args.data());
     1021        DeferTraps deferTraps(vm); // We can't jettison this code if we're about to run it.
     1022
     1023        CodeBlock* newCodeBlock = nullptr;
     1024        if (isJSCall) {
     1025            // Compile the callee:
     1026            callData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(function), scope, CodeForCall, newCodeBlock);
     1027            RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
     1028
     1029            ASSERT(newCodeBlock);
     1030            newCodeBlock->m_shouldAlwaysBeInlined = false;
     1031        }
     1032
     1033        {
     1034            DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
     1035            if (isJSCall)
     1036                jitCode = callData.js.functionExecutable->generatedJITCodeForCall();
     1037            protoCallFrame.init(newCodeBlock, globalObject, function, thisValue, argsCount, args.data());
     1038        }
    10311039    }
    10321040
     
    10881096    }
    10891097
    1090     CodeBlock* newCodeBlock = nullptr;
    1091     if (isJSConstruct) {
    1092         // Compile the callee:
    1093         constructData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(constructor), scope, CodeForConstruct, newCodeBlock);
    1094         RETURN_IF_EXCEPTION(throwScope, nullptr);
    1095 
    1096         ASSERT(newCodeBlock);
    1097         newCodeBlock->m_shouldAlwaysBeInlined = false;
    1098     }
    1099 
    11001098    RefPtr<JITCode> jitCode;
    11011099    ProtoCallFrame protoCallFrame;
    11021100    {
    1103         DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
    1104         if (isJSConstruct)
    1105             jitCode = constructData.js.functionExecutable->generatedJITCodeForConstruct();
    1106         protoCallFrame.init(newCodeBlock, globalObject, constructor, newTarget, argsCount, args.data());
     1101        DeferTraps deferTraps(vm); // We can't jettison this code if we're about to run it.
     1102
     1103        CodeBlock* newCodeBlock = nullptr;
     1104        if (isJSConstruct) {
     1105            // Compile the callee:
     1106            constructData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(constructor), scope, CodeForConstruct, newCodeBlock);
     1107            RETURN_IF_EXCEPTION(throwScope, nullptr);
     1108
     1109            ASSERT(newCodeBlock);
     1110            newCodeBlock->m_shouldAlwaysBeInlined = false;
     1111        }
     1112
     1113        {
     1114            DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
     1115            if (isJSConstruct)
     1116                jitCode = constructData.js.functionExecutable->generatedJITCodeForConstruct();
     1117            protoCallFrame.init(newCodeBlock, globalObject, constructor, newTarget, argsCount, args.data());
     1118        }
    11071119    }
    11081120
     
    12961308        callee = JSCallee::create(vm, globalObject, scope);
    12971309
    1298     // Reload CodeBlock. It is possible that we replaced CodeBlock while setting up the environment.
    1299     {
    1300         CodeBlock* tempCodeBlock;
    1301         eval->prepareForExecution<EvalExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
    1302         RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
    1303 
    1304         codeBlock = jsCast<EvalCodeBlock*>(tempCodeBlock);
    1305         ASSERT(codeBlock && codeBlock->numParameters() == 1); // 1 parameter for 'this'.
    1306     }
    1307 
    13081310    RefPtr<JITCode> jitCode;
    13091311    ProtoCallFrame protoCallFrame;
    13101312    {
    1311         DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
    1312         jitCode = eval->generatedJITCode();
    1313         protoCallFrame.init(codeBlock, globalObject, callee, thisValue, 1);
     1313        DeferTraps deferTraps(vm); // We can't jettison this code if we're about to run it.
     1314
     1315        // Reload CodeBlock. It is possible that we replaced CodeBlock while setting up the environment.
     1316        {
     1317            CodeBlock* tempCodeBlock;
     1318            eval->prepareForExecution<EvalExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
     1319            RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
     1320
     1321            codeBlock = jsCast<EvalCodeBlock*>(tempCodeBlock);
     1322            ASSERT(codeBlock && codeBlock->numParameters() == 1); // 1 parameter for 'this'.
     1323        }
     1324
     1325        {
     1326            DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
     1327            jitCode = eval->generatedJITCode();
     1328            protoCallFrame.init(codeBlock, globalObject, callee, thisValue, 1);
     1329        }
    13141330    }
    13151331
     
    13531369    const unsigned numberOfArguments = static_cast<unsigned>(AbstractModuleRecord::Argument::NumberOfArguments);
    13541370    JSCallee* callee = JSCallee::create(vm, globalObject, scope);
    1355     ModuleProgramCodeBlock* codeBlock;
    1356     {
    1357         CodeBlock* tempCodeBlock;
    1358         executable->prepareForExecution<ModuleProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
    1359         RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
    1360 
    1361         codeBlock = jsCast<ModuleProgramCodeBlock*>(tempCodeBlock);
    1362         ASSERT(codeBlock && codeBlock->numParameters() == numberOfArguments + 1);
    1363     }
    1364 
    13651371    RefPtr<JITCode> jitCode;
     1372
    13661373    ProtoCallFrame protoCallFrame;
    13671374    JSValue args[numberOfArguments] = {
     
    13741381
    13751382    {
    1376         DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
    1377         jitCode = executable->generatedJITCode();
    1378 
    1379         // The |this| of the module is always `undefined`.
    1380         // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-hasthisbinding
    1381         // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-getthisbinding
    1382         protoCallFrame.init(codeBlock, globalObject, callee, jsUndefined(), numberOfArguments + 1, args);
    1383     }
    1384 
    1385     record->internalField(JSModuleRecord::Field::State).set(vm, record, jsNumber(static_cast<int>(JSModuleRecord::State::Executing)));
     1383        DeferTraps deferTraps(vm); // We can't jettison this code if we're about to run it.
     1384
     1385        ModuleProgramCodeBlock* codeBlock;
     1386        {
     1387            CodeBlock* tempCodeBlock;
     1388            executable->prepareForExecution<ModuleProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
     1389            RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
     1390
     1391            codeBlock = jsCast<ModuleProgramCodeBlock*>(tempCodeBlock);
     1392            ASSERT(codeBlock && codeBlock->numParameters() == numberOfArguments + 1);
     1393        }
     1394
     1395
     1396        {
     1397            DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
     1398            jitCode = executable->generatedJITCode();
     1399
     1400            // The |this| of the module is always `undefined`.
     1401            // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-hasthisbinding
     1402            // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-getthisbinding
     1403            protoCallFrame.init(codeBlock, globalObject, callee, jsUndefined(), numberOfArguments + 1, args);
     1404        }
     1405
     1406        record->internalField(JSModuleRecord::Field::State).set(vm, record, jsNumber(static_cast<int>(JSModuleRecord::State::Executing)));
     1407    }
    13861408
    13871409    // Execute the code:
  • trunk/Source/JavaScriptCore/interpreter/InterpreterInlines.h

    r290769 r290788  
    3737#include "ProtoCallFrameInlines.h"
    3838#include "UnlinkedCodeBlock.h"
     39#include "VMTrapsInlines.h"
    3940#include <wtf/UnalignedAccess.h>
    4041
     
    8788    }
    8889
    89     // Reload CodeBlock since GC can replace CodeBlock owned by Executable.
    90     CodeBlock* codeBlock;
    91     closure.functionExecutable->prepareForExecution<FunctionExecutable>(vm, closure.function, closure.scope, CodeForCall, codeBlock);
    92     RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
     90    {
     91        DeferTraps deferTraps(vm); // We can't jettison this code if we're about to run it.
    9392
    94     ASSERT(codeBlock);
    95     codeBlock->m_shouldAlwaysBeInlined = false;
    96     {
    97         DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
    98         closure.protoCallFrame->setCodeBlock(codeBlock);
     93        // Reload CodeBlock since GC can replace CodeBlock owned by Executable.
     94        CodeBlock* codeBlock;
     95        closure.functionExecutable->prepareForExecution<FunctionExecutable>(vm, closure.function, closure.scope, CodeForCall, codeBlock);
     96        RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
     97
     98        ASSERT(codeBlock);
     99        codeBlock->m_shouldAlwaysBeInlined = false;
     100        {
     101            DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
     102            closure.protoCallFrame->setCodeBlock(codeBlock);
     103        }
    99104    }
     105
    100106    // Execute the code:
    101107    throwScope.release();
    102108    JSValue result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame);
    103 
    104109    return checkedReturn(result);
    105110}
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r290769 r290788  
    6767#include "SuperSampler.h"
    6868#include "VMInlines.h"
     69#include "VMTrapsInlines.h"
    6970#include <wtf/NeverDestroyed.h>
    7071#include <wtf/StringPrintStream.h>
     
    19051906    ExecutableBase* executable = callee->executable();
    19061907
     1908    DeferTraps deferTraps(vm); // We can't jettison this code if we're about to run it.
     1909
    19071910    MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
    1908     CodeBlock* codeBlock = nullptr;
    19091911    // FIXME: Support wasm IC.
    19101912    // https://bugs.webkit.org/show_bug.cgi?id=220339
     
    19201922        LLINT_CALL_CHECK_EXCEPTION(globalObject);
    19211923
    1922         codeBlock = *codeBlockSlot;
     1924        CodeBlock* codeBlock = *codeBlockSlot;
    19231925        ASSERT(codeBlock);
    19241926
  • trunk/Source/JavaScriptCore/runtime/ExceptionScope.h

    r277068 r290788  
    111111        JSC::VM& vm = (scope__).vm(); \
    112112        ASSERT(!!(scope__).exception() == vm.traps().needHandling(JSC::VMTraps::NeedExceptionHandling)); \
    113         if (UNLIKELY(vm.traps().needHandling(JSC::VMTraps::NonDebuggerEvents))) { \
     113        if (UNLIKELY(vm.traps().maybeNeedHandling(JSC::VMTraps::NonDebuggerEvents))) { \
    114114            if (vm.hasExceptionsAfterHandlingTraps()) \
    115115                return value__; \
  • trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp

    r290769 r290788  
    197197        RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
    198198        RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
     199
     200        genericCodeBlock->m_isJettisoned = false;
    199201       
    200202        dataLogLnIf(Options::verboseOSR(), "Installing ", *genericCodeBlock);
  • trunk/Source/JavaScriptCore/runtime/VMTraps.cpp

    r290769 r290788  
    350350    ASSERT(onlyContainsAsyncEvents(mask));
    351351    ASSERT(needHandling(mask));
     352    ASSERT(!hasTrapBit(DeferTrapHandling));
    352353
    353354    if (isDeferringTermination())
     
    391392
    392393        case NeedExceptionHandling:
     394        case DeferTrapHandling:
    393395        default:
    394396            RELEASE_ASSERT_NOT_REACHED();
     
    403405    // Note: the EventBitShift is already sorted in highest to lowest priority
    404406    // i.e. a bit shift of 0 is highest priority, etc.
    405     for (int i = 0; i < NumberOfEvents; ++i) {
     407    for (unsigned i = 0; i < NumberOfEvents; ++i) {
    406408        Event event = static_cast<Event>(1 << i);
    407409        if (hasTrapBit(event, mask)) {
  • trunk/Source/JavaScriptCore/runtime/VMTraps.h

    r290769 r290788  
    150150    v(NeedWatchdogCheck) \
    151151    v(NeedDebuggerBreak) \
    152     v(NeedExceptionHandling)
     152    v(NeedExceptionHandling) \
     153    v(DeferTrapHandling) // Must come last in the enum. This defers all events except NeedExceptionHandling.
    153154
    154155#define DECLARE_VMTRAPS_EVENT_BIT_SHIFT(event__)  event__##BitShift,
    155156    enum EventBitShift {
    156157        FOR_EACH_VMTRAPS_EVENTS(DECLARE_VMTRAPS_EVENT_BIT_SHIFT)
    157         NumberOfEvents, // This entry must be last in this list.
    158158    };
    159159#undef DECLARE_VMTRAPS_EVENT_BIT_SHIFT
     160
     161
     162#define COUNT_EVENT(event) + 1
     163    static constexpr BitField NumberOfEvents = FOR_EACH_VMTRAPS_EVENTS(COUNT_EVENT) - 1; // Don't count DeferTrapHandling.
     164    static constexpr BitField NumberOfEventsIncludingDefer = FOR_EACH_VMTRAPS_EVENTS(COUNT_EVENT);
     165#undef COUNT_EVENT
    160166
    161167    using Event = BitField;
     
    171177    static constexpr Event NoEvent = 0;
    172178
    173     static_assert(NumberOfEvents <= bitsInBitField);
     179    static_assert(NumberOfEventsIncludingDefer <= bitsInBitField);
    174180    static constexpr BitField AllEvents = (1ull << NumberOfEvents) - 1;
     181    static constexpr BitField AllEventsIncludingDefer = (1ull << NumberOfEventsIncludingDefer) - 1;
    175182    static constexpr BitField AsyncEvents = AllEvents & ~NeedExceptionHandling;
    176183    static constexpr BitField NonDebuggerEvents = AllEvents & ~NeedDebuggerBreak;
     
    189196    void willDestroyVM();
    190197
    191     bool needHandling(BitField mask) const { return m_trapBits.loadRelaxed() & mask; }
     198    ALWAYS_INLINE bool needHandling(BitField mask) const
     199    {
     200        auto maskedValue = m_trapBits.loadRelaxed() & (mask | DeferTrapHandling);
     201        if (UNLIKELY(maskedValue))
     202            return (maskedValue & NeedExceptionHandling) || !(maskedValue & DeferTrapHandling);
     203        return false;
     204    }
     205    // Designed to be a fast check to rule out if we might need handling, and we need to ensure needHandling on the slow path.
     206    ALWAYS_INLINE bool maybeNeedHandling(BitField mask) const { return m_trapBits.loadRelaxed() & mask; }
    192207    void* trapBitsAddress() { return &m_trapBits; }
    193208
     
    207222    }
    208223
     224    bool hasTrapBit(Event event)
     225    {
     226        return m_trapBits.loadRelaxed() & event;
     227    }
    209228    bool hasTrapBit(Event event, BitField mask)
    210229    {
     
    215234    void setTrapBit(Event event)
    216235    {
    217         ASSERT((event & ~AllEvents) == 0);
     236        ASSERT((event & ~AllEventsIncludingDefer) == 0);
    218237        m_trapBits.exchangeOr(event);
    219238    }
     
    267286};
    268287
     288class DeferTraps {
     289public:
     290    DeferTraps(VM&);
     291    ~DeferTraps();
     292private:
     293    VMTraps& m_traps;
     294    bool m_isActive;
     295};
     296
    269297} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/VMTrapsInlines.h

    r290769 r290788  
    5151}
    5252
     53ALWAYS_INLINE DeferTraps::DeferTraps(VM& vm)
     54    : m_traps(vm.traps())
     55    , m_isActive(!m_traps.hasTrapBit(VMTraps::DeferTrapHandling))
     56{
     57    if (m_isActive)
     58        m_traps.setTrapBit(VMTraps::DeferTrapHandling);
     59}
     60
     61ALWAYS_INLINE DeferTraps::~DeferTraps()
     62{
     63    if (m_isActive)
     64        m_traps.clearTrapBit(VMTraps::DeferTrapHandling);
     65}
     66
    5367} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.