Changeset 262362 in webkit


Ignore:
Timestamp:
May 31, 2020 7:56:06 AM (4 years ago)
Author:
msaboff@apple.com
Message:

Consider a Thread Specific Cache for AssemblerBuffers
https://bugs.webkit.org/show_bug.cgi?id=212562

Reviewed by Filip Pizlo.

This patch creates a thread local cache of AssemblerData in the hopes that it will reduce
memory allocation churn. The cache is cleared when a thread is destroyed.
If an AssemblerData is destroyed in another thread, its storage is cached by the
destroying thread.

Made a few changes described below to facilite the swap as well as returning a
clear()'ed AssemblerData back to its original state.

Reviewed by Filip Pizlo.

  • assembler/AssemblerBuffer.cpp:

(JSC::threadSpecificAssemblerData):
(JSC::clearAssembleDataThreadSpecificCache):

  • assembler/AssemblerBuffer.h:

(JSC::AssemblerData::AssemblerData):
(JSC::AssemblerData::operator=):
The copy constructor and assignment operator now perform complete AssemblerBuffer swaps.

(JSC::AssemblerData::takeBufferIfLarger):
A new method that will conditionally copy the enclosed buffer of the argument to "this"
if the argument's buffer is larger than the current buffer of "this".

(JSC::AssemblerData::~AssemblerData):
(JSC::AssemblerData::clear):
The destructor now calls clear which has been changed to reset the buffer to one with
inline capacity.

(JSC::AssemblerBuffer::AssemblerBuffer):
Take the cached out of line buffer if there is one.

(JSC::AssemblerBuffer::~AssemblerBuffer):
Cache the enclosed out of line buffer if it is larger than the currently cached one.

(JSC::AssemblerBuffer::getThreadSpecificAssemblerData):

  • dfg/DFGWorklist.cpp:
  • jit/JITWorklist.cpp:
  • wasm/WasmWorklist.cpp:
Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r262356 r262362  
     12020-05-31  Michael Saboff  <msaboff@apple.com>
     2
     3        Consider a Thread Specific Cache for AssemblerBuffers
     4        https://bugs.webkit.org/show_bug.cgi?id=212562
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch creates a thread local cache of AssemblerData in the hopes that it will reduce
     9        memory allocation churn.  The cache is cleared when a thread is destroyed.
     10        If an AssemblerData is destroyed in another thread, its storage is cached by the
     11        destroying thread.
     12
     13        Made a few changes described below to facilite the swap as well as returning a
     14        clear()'ed AssemblerData back to its original state.
     15
     16        Reviewed by Filip Pizlo.
     17
     18        * assembler/AssemblerBuffer.cpp:
     19        (JSC::threadSpecificAssemblerData):
     20        (JSC::clearAssembleDataThreadSpecificCache):
     21        * assembler/AssemblerBuffer.h:
     22
     23        (JSC::AssemblerData::AssemblerData):
     24        (JSC::AssemblerData::operator=):
     25        The copy constructor and assignment operator now perform complete AssemblerBuffer swaps.
     26
     27        (JSC::AssemblerData::takeBufferIfLarger):
     28        A new method that will conditionally copy the enclosed buffer of the argument to "this"
     29        if the argument's buffer is larger than the current buffer of "this".
     30
     31        (JSC::AssemblerData::~AssemblerData):
     32        (JSC::AssemblerData::clear):
     33        The destructor now calls clear which has been changed to reset the buffer to one with
     34        inline capacity.
     35
     36        (JSC::AssemblerBuffer::AssemblerBuffer):
     37        Take the cached out of line buffer if there is one.
     38
     39        (JSC::AssemblerBuffer::~AssemblerBuffer):
     40        Cache the enclosed out of line buffer if it is larger than the currently cached one.
     41
     42        (JSC::AssemblerBuffer::getThreadSpecificAssemblerData):
     43        * dfg/DFGWorklist.cpp:
     44        * jit/JITWorklist.cpp:
     45        * wasm/WasmWorklist.cpp:
     46
    1472020-05-31  Mark Lam  <mark.lam@apple.com>
    248
  • trunk/Source/JavaScriptCore/assembler/AssemblerBuffer.cpp

    r261755 r262362  
    3131DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(AssemblerData);
    3232
     33#if ENABLE(ASSEMBLER)
     34
     35static ThreadSpecificAssemblerData* threadSpecificAssemblerDataPtr;
     36
     37ThreadSpecificAssemblerData& threadSpecificAssemblerData()
     38{
     39    static std::once_flag flag;
     40    std::call_once(
     41        flag,
     42        [] () {
     43            threadSpecificAssemblerDataPtr = new ThreadSpecificAssemblerData();
     44        });
     45    return *threadSpecificAssemblerDataPtr;
     46}
     47
     48void clearAssembleDataThreadSpecificCache()
     49{
     50    auto& threadSpecific = threadSpecificAssemblerData();
     51    if (threadSpecific.isSet())
     52        threadSpecific->clear();
     53}
     54
     55#endif // ENABLE(ASSEMBLER)
     56
    3357} // namespace JSC
  • trunk/Source/JavaScriptCore/assembler/AssemblerBuffer.h

    r254087 r262362  
    3838#endif
    3939#include <wtf/StdLibExtras.h>
     40#include <wtf/ThreadSpecific.h>
    4041#include <wtf/UnalignedAccess.h>
    4142
    4243namespace JSC {
     44    class AssemblerData;
     45
     46    typedef ThreadSpecific<AssemblerData, WTF::CanBeGCThread::True> ThreadSpecificAssemblerData;
     47
     48    JS_EXPORT_PRIVATE ThreadSpecificAssemblerData& threadSpecificAssemblerData();
     49    void clearAssembleDataThreadSpecificCache();
    4350
    4451    class LinkBuffer;
     
    100107            m_capacity = other.m_capacity;
    101108
    102             other.m_buffer = nullptr;
    103             other.m_capacity = 0;
     109            other.m_buffer = other.m_inlineBuffer;
     110            other.m_capacity = InlineCapacity;
    104111        }
    105112
     
    117124            m_capacity = other.m_capacity;
    118125
    119             other.m_buffer = nullptr;
    120             other.m_capacity = 0;
     126            other.m_buffer = other.m_inlineBuffer;
     127            other.m_capacity = InlineCapacity;
    121128            return *this;
    122129        }
    123130
    124         ~AssemblerData()
    125         {
     131        void takeBufferIfLarger(AssemblerData&& other)
     132        {
     133            if (other.isInlineBuffer())
     134                return;
     135
     136            if (m_capacity >= other.m_capacity)
     137                return;
     138
    126139            if (m_buffer && !isInlineBuffer())
    127140                AssemblerDataMalloc::free(m_buffer);
     141
     142            m_buffer = other.m_buffer;
     143            m_capacity = other.m_capacity;
     144
     145            other.m_buffer = other.m_inlineBuffer;
     146            other.m_capacity = InlineCapacity;
     147        }
     148
     149        ~AssemblerData()
     150        {
     151            clear();
     152        }
     153
     154        void clear()
     155        {
     156            if (m_buffer && !isInlineBuffer()) {
     157                AssemblerDataMalloc::free(m_buffer);
     158                m_capacity = InlineCapacity;
     159                m_buffer = m_inlineBuffer;
     160            }
    128161        }
    129162
     
    178211            , m_index(0)
    179212        {
     213            auto& threadSpecific = getThreadSpecificAssemblerData();
     214            m_storage.takeBufferIfLarger(WTFMove(*threadSpecific));
     215        }
     216
     217        ~AssemblerBuffer()
     218        {
     219            auto& threadSpecific = getThreadSpecificAssemblerData();
     220            threadSpecific->takeBufferIfLarger(WTFMove(m_storage));
    180221        }
    181222
     
    294335
    295336    protected:
     337        ThreadSpecificAssemblerData& getThreadSpecificAssemblerData()
     338        {
     339            auto& threadSpecific = threadSpecificAssemblerData();
     340
     341            if (!threadSpecific.isSet()) {
     342                void* ptr = static_cast<AssemblerData*>(threadSpecific);
     343                new (ptr) AssemblerData();
     344            }
     345
     346            return threadSpecific;
     347        }
     348       
    296349        template<typename IntegralType>
    297350        void putIntegral(IntegralType value)
  • trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp

    r261895 r262362  
    159159        ASSERT(!m_plan);
    160160       
     161        clearAssembleDataThreadSpecificCache();
    161162        m_compilationScope = nullptr;
    162163        m_plan = nullptr;
  • trunk/Source/JavaScriptCore/jit/JITWorklist.cpp

    r261755 r262362  
    145145        m_worklist.m_numAvailableThreads++;
    146146        return WorkResult::Continue;
     147    }
     148
     149    void threadIsStopping(const AbstractLocker&) final
     150    {
     151        clearAssembleDataThreadSpecificCache();
    147152    }
    148153
  • trunk/Source/JavaScriptCore/wasm/WasmWorklist.cpp

    r261569 r262362  
    121121    {
    122122        clearLLIntThreadSpecificCache();
     123        clearAssembleDataThreadSpecificCache();
    123124    }
    124125
Note: See TracChangeset for help on using the changeset viewer.