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

Changeset 276069 in webkit


Ignore:
Timestamp:
Apr 15, 2021, 1:31:04 PM (5 years ago)
Author:
mark.lam@apple.com
Message:

Optimize the DeferTermination scope to be more efficient.
https://bugs.webkit.org/show_bug.cgi?id=224619

Reviewed by Saam Barati.

Source/JavaScriptCore:

This can be beneficial since we may be using DeferTermination in more places in
the code.

  1. Added a VMTrapsInlines.h to hold the inline functions.
  1. Split deferTermination() and undoDeferTermination() into fast and slow functions. The fast functions are inlineable.
  1. Remove the locking of VMTraps::m_lock in these functions. These functions only modify the following:
    1. VMTraps::m_deferTerminationCount
    2. VMTraps::m_suspendedTerminationException
    3. VMTraps::m_trapBits for setting the NeedTermination bit if needed.
    4. VM::m_exception

Except for VMTraps::m_trapBits, all of these are only written to from the mutator
thread. VMTraps::m_trapBits is always written to using Atomics. There isn't
anything that needs to be guarded by VMTraps::m_lock.

  1. Fix VMTraps::deferTermination() to only set m_suspendedTerminationException and clear an existing TerminationException if it's being called from the outermost DeferTermination (i.e. m_deferTerminationCount is 1 after incrementing). These conditional operations are not done in VMTraps::deferTerminationSlow().

In practice, it wouldn't have mattered anyway because we would never throw a
TerminationException while a DeferTermination scope is in effect. The
the vm.isTerminationException() in the original deferTermination() would
always have prevented the slow path operations from being executed anyway.

However, for the purpose of this patch, we want to avoid as much unnecessary
work as possible in the fast path. Hence, it is good to skip the slow path
if deferTermination() isn't called from the outermost scope.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • jit/JITOperations.cpp:
  • jsc.cpp:
  • runtime/JSGlobalObject.cpp:
  • runtime/VMTraps.cpp:

(JSC::VMTraps::deferTerminationSlow):
(JSC::VMTraps::undoDeferTerminationSlow):
(JSC::VMTraps::vm const): Deleted.
(JSC::VMTraps::deferTermination): Deleted.
(JSC::VMTraps::undoDeferTermination): Deleted.

  • runtime/VMTraps.h:
  • runtime/VMTrapsInlines.h: Added.

(JSC::VMTraps::vm const):
(JSC::VMTraps::deferTermination):
(JSC::VMTraps::undoDeferTermination):

Source/WebCore:

  • workers/WorkerOrWorkletScriptController.cpp:
Location:
trunk/Source
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r276039 r276069  
    11041104    runtime/VMInlines.h
    11051105    runtime/VMTraps.h
     1106    runtime/VMTrapsInlines.h
    11061107    runtime/VarOffset.h
    11071108    runtime/Watchdog.h
  • trunk/Source/JavaScriptCore/ChangeLog

    r276039 r276069  
     12021-04-15  Mark Lam  <mark.lam@apple.com>
     2
     3        Optimize the DeferTermination scope to be more efficient.
     4        https://bugs.webkit.org/show_bug.cgi?id=224619
     5
     6        Reviewed by Saam Barati.
     7
     8        This can be beneficial since we may be using DeferTermination in more places in
     9        the code.
     10
     11        1. Added a VMTrapsInlines.h to hold the inline functions.
     12
     13        2. Split deferTermination() and undoDeferTermination() into fast and slow functions.
     14           The fast functions are inlineable.
     15
     16        3. Remove the locking of VMTraps::m_lock in these functions.  These functions only
     17           modify the following:
     18           a. VMTraps::m_deferTerminationCount
     19           b. VMTraps::m_suspendedTerminationException
     20           c. VMTraps::m_trapBits for setting the NeedTermination bit if needed.
     21           d. VM::m_exception
     22
     23           Except for VMTraps::m_trapBits, all of these are only written to from the mutator
     24           thread.  VMTraps::m_trapBits is always written to using Atomics.  There isn't
     25           anything that needs to be guarded by VMTraps::m_lock.
     26
     27        4. Fix VMTraps::deferTermination() to only set m_suspendedTerminationException
     28           and clear an existing TerminationException if it's being called from the
     29           outermost DeferTermination (i.e. m_deferTerminationCount is 1 after incrementing).
     30           These conditional operations are not done in VMTraps::deferTerminationSlow().
     31
     32           In practice, it wouldn't have mattered anyway because we would never throw a
     33           TerminationException while a DeferTermination scope is in effect.  The
     34           the vm.isTerminationException() in the original deferTermination() would
     35           always have prevented the slow path operations from being executed anyway.
     36
     37           However, for the purpose of this patch, we want to avoid as much unnecessary
     38           work as possible in the fast path.  Hence, it is good to skip the slow path
     39           if deferTermination() isn't called from the outermost scope.
     40
     41        * CMakeLists.txt:
     42        * JavaScriptCore.xcodeproj/project.pbxproj:
     43        * jit/JITOperations.cpp:
     44        * jsc.cpp:
     45        * runtime/JSGlobalObject.cpp:
     46        * runtime/VMTraps.cpp:
     47        (JSC::VMTraps::deferTerminationSlow):
     48        (JSC::VMTraps::undoDeferTerminationSlow):
     49        (JSC::VMTraps::vm const): Deleted.
     50        (JSC::VMTraps::deferTermination): Deleted.
     51        (JSC::VMTraps::undoDeferTermination): Deleted.
     52        * runtime/VMTraps.h:
     53        * runtime/VMTrapsInlines.h: Added.
     54        (JSC::VMTraps::vm const):
     55        (JSC::VMTraps::deferTermination):
     56        (JSC::VMTraps::undoDeferTermination):
     57
    1582021-04-15  Mark Lam  <mark.lam@apple.com>
    259
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r276039 r276069  
    20162016                FEF5B4272628ABD90016E776 /* JSWeakMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF5B4262628ABD90016E776 /* JSWeakMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20172017                FEF5B4292628B5240016E776 /* JSSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF5B4282628B5240016E776 /* JSSetInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
     2018                FEF5B42C2628CBC80016E776 /* VMTrapsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF5B42B2628CBC80016E776 /* VMTrapsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20182019                FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20192020/* End PBXBuildFile section */
     
    54265427                FEF5B4262628ABD90016E776 /* JSWeakMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakMapInlines.h; sourceTree = "<group>"; };
    54275428                FEF5B4282628B5240016E776 /* JSSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSetInlines.h; sourceTree = "<group>"; };
     5429                FEF5B42B2628CBC80016E776 /* VMTrapsInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMTrapsInlines.h; sourceTree = "<group>"; };
    54285430                FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
    54295431/* End PBXFileReference section */
     
    79217923                                FE6F56DC1E64E92000D17801 /* VMTraps.cpp */,
    79227924                                FE6F56DD1E64E92000D17801 /* VMTraps.h */,
     7925                                FEF5B42B2628CBC80016E776 /* VMTrapsInlines.h */,
    79237926                                FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
    79247927                                FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
     
    98229825                                52EED7942492B870008F4C93 /* FunctionAllowlist.h in Headers */,
    98239826                                14AD910D1DCA92940014F9FE /* FunctionCodeBlock.h in Headers */,
     9827                                FEF5B42C2628CBC80016E776 /* VMTrapsInlines.h in Headers */,
    98249828                                BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */,
    98259829                                147341D81DC02F9900AA29BA /* FunctionExecutable.h in Headers */,
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r276000 r276069  
    6868#include "TypeProfilerLog.h"
    6969#include "VMInlines.h"
     70#include "VMTrapsInlines.h"
    7071
    7172IGNORE_WARNINGS_BEGIN("frame-address")
  • trunk/Source/JavaScriptCore/jsc.cpp

    r275971 r276069  
    7070#include "TypedArrayInlines.h"
    7171#include "VMInspector.h"
     72#include "VMTrapsInlines.h"
    7273#include "WasmCapabilities.h"
    7374#include "WasmFaultSignalHandler.h"
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r275845 r276069  
    202202#include "SymbolObject.h"
    203203#include "SymbolPrototype.h"
     204#include "VMTrapsInlines.h"
    204205#include "WasmCapabilities.h"
    205206#include "WeakMapConstructor.h"
  • trunk/Source/JavaScriptCore/runtime/VMTraps.cpp

    r275969 r276069  
    3737#include "MachineContext.h"
    3838#include "MacroAssemblerCodeRef.h"
    39 #include "VM.h"
     39#include "VMTrapsInlines.h"
    4040#include "Watchdog.h"
    4141#include <wtf/ProcessID.h>
     
    4444
    4545namespace JSC {
    46 
    47 ALWAYS_INLINE VM& VMTraps::vm() const
    48 {
    49     return *bitwise_cast<VM*>(bitwise_cast<uintptr_t>(this) - OBJECT_OFFSETOF(VM, m_traps));
    50 }
    5146
    5247#if ENABLE(SIGNAL_BASED_VM_TRAPS)
     
    416411}
    417412
    418 void VMTraps::deferTermination(DeferAction)
    419 {
    420     auto locker = holdLock(*m_lock);
    421     m_deferTerminationCount++;
    422     ASSERT(m_deferTerminationCount < UINT_MAX);
     413void VMTraps::deferTerminationSlow(DeferAction)
     414{
     415    ASSERT(m_deferTerminationCount == 1);
    423416
    424417    VM& vm = this->vm();
    425418    Exception* pendingException = vm.exception();
    426     if (pendingException && vm.isTerminationException(pendingException)) {
     419    ASSERT(pendingException);
     420    if (vm.isTerminationException(pendingException)) {
     421        ASSERT(vm.terminationInProgress());
    427422        vm.clearException();
    428423        m_suspendedTerminationException = true;
     
    430425}
    431426
    432 void VMTraps::undoDeferTermination(DeferAction action)
    433 {
    434     auto locker = holdLock(*m_lock);
    435     ASSERT(m_deferTerminationCount > 0);
    436     if (--m_deferTerminationCount == 0) {
    437         VM& vm = this->vm();
    438         if (m_suspendedTerminationException
    439             || ((action == DeferAction::DeferUntilEndOfScope) && vm.terminationInProgress()))
    440             vm.throwTerminationException();
    441         else if ((action == DeferAction::DeferForAWhile) && vm.terminationInProgress())
    442             setTrapBit(NeedTermination); // Let the next trap check handle it.
    443     }
     427void VMTraps::undoDeferTerminationSlow(DeferAction deferAction)
     428{
     429    ASSERT(m_deferTerminationCount == 0);
     430
     431    VM& vm = this->vm();
     432    ASSERT(vm.terminationInProgress());
     433    if (m_suspendedTerminationException || (deferAction == DeferAction::DeferUntilEndOfScope)) {
     434        vm.throwTerminationException();
     435        m_suspendedTerminationException = false;
     436    } else if (deferAction == DeferAction::DeferForAWhile)
     437        setTrapBit(NeedTermination); // Let the next trap check handle it.
    444438}
    445439
  • trunk/Source/JavaScriptCore/runtime/VMTraps.h

    r275969 r276069  
    198198
    199199    bool isDeferringTermination() const { return m_deferTerminationCount; }
    200     JS_EXPORT_PRIVATE void deferTermination(DeferAction);
    201     JS_EXPORT_PRIVATE void undoDeferTermination(DeferAction);
     200    void deferTermination(DeferAction);
     201    void undoDeferTermination(DeferAction);
    202202
    203203    void notifyGrabAllLocks()
     
    227227    VM& vm() const;
    228228
     229    JS_EXPORT_PRIVATE void deferTerminationSlow(DeferAction);
     230    JS_EXPORT_PRIVATE void undoDeferTerminationSlow(DeferAction);
    229231    Event takeTopPriorityTrap(BitField mask);
    230232
  • trunk/Source/WebCore/ChangeLog

    r276052 r276069  
     12021-04-15  Mark Lam  <mark.lam@apple.com>
     2
     3        Optimize the DeferTermination scope to be more efficient.
     4        https://bugs.webkit.org/show_bug.cgi?id=224619
     5
     6        Reviewed by Saam Barati.
     7
     8        * workers/WorkerOrWorkletScriptController.cpp:
     9
    1102021-04-15  Antoine Quint  <graouts@webkit.org>
    211
  • trunk/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp

    r275845 r276069  
    5858#include <JavaScriptCore/ScriptCallStack.h>
    5959#include <JavaScriptCore/StrongInlines.h>
     60#include <JavaScriptCore/VMTrapsInlines.h>
    6061
    6162namespace WebCore {
Note: See TracChangeset for help on using the changeset viewer.