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

Changeset 243408 in webkit


Ignore:
Timestamp:
Mar 23, 2019, 12:58:07 AM (7 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Shrink sizeof(RegExp)
https://bugs.webkit.org/show_bug.cgi?id=196133

Reviewed by Mark Lam.

Some applications have many RegExp cells. But RegExp cells are very large (144B).
This patch reduces the size from 144B to 48B by,

  1. Allocate Yarr::YarrCodeBlock in non-GC heap. We can avoid this allocation if JIT is disabled.
  2. m_captureGroupNames and m_namedGroupToParenIndex are moved to RareData. They are only used when RegExp has named capture groups.
  • runtime/RegExp.cpp:

(JSC::RegExp::finishCreation):
(JSC::RegExp::estimatedSize):
(JSC::RegExp::compile):
(JSC::RegExp::matchConcurrently):
(JSC::RegExp::compileMatchOnly):
(JSC::RegExp::deleteCode):
(JSC::RegExp::printTraceData):

  • runtime/RegExp.h:
  • runtime/RegExpInlines.h:

(JSC::RegExp::hasCodeFor):
(JSC::RegExp::matchInline):
(JSC::RegExp::hasMatchOnlyCodeFor):

Location:
trunk/Source/JavaScriptCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r243396 r243408  
     12019-03-23  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Shrink sizeof(RegExp)
     4        https://bugs.webkit.org/show_bug.cgi?id=196133
     5
     6        Reviewed by Mark Lam.
     7
     8        Some applications have many RegExp cells. But RegExp cells are very large (144B).
     9        This patch reduces the size from 144B to 48B by,
     10
     11        1. Allocate Yarr::YarrCodeBlock in non-GC heap. We can avoid this allocation if JIT is disabled.
     12        2. m_captureGroupNames and m_namedGroupToParenIndex are moved to RareData. They are only used when RegExp has named capture groups.
     13
     14        * runtime/RegExp.cpp:
     15        (JSC::RegExp::finishCreation):
     16        (JSC::RegExp::estimatedSize):
     17        (JSC::RegExp::compile):
     18        (JSC::RegExp::matchConcurrently):
     19        (JSC::RegExp::compileMatchOnly):
     20        (JSC::RegExp::deleteCode):
     21        (JSC::RegExp::printTraceData):
     22        * runtime/RegExp.h:
     23        * runtime/RegExpInlines.h:
     24        (JSC::RegExp::hasCodeFor):
     25        (JSC::RegExp::matchInline):
     26        (JSC::RegExp::hasMatchOnlyCodeFor):
     27
    1282019-03-22  Keith Rollin  <krollin@apple.com>
    229
  • trunk/Source/JavaScriptCore/runtime/RegExp.cpp

    r242699 r243408  
    172172    Base::finishCreation(vm);
    173173    Yarr::YarrPattern pattern(m_patternString, m_flags, m_constructionErrorCode, vm.stackLimit());
    174     if (!isValid())
     174    if (!isValid()) {
    175175        m_state = ParseError;
    176     else {
    177         m_numSubpatterns = pattern.m_numSubpatterns;
    178         m_captureGroupNames.swap(pattern.m_captureGroupNames);
    179         m_namedGroupToParenIndex.swap(pattern.m_namedGroupToParenIndex);
     176        return;
     177    }
     178
     179    m_numSubpatterns = pattern.m_numSubpatterns;
     180    if (!pattern.m_captureGroupNames.isEmpty() || !pattern.m_namedGroupToParenIndex.isEmpty()) {
     181        m_rareData = std::make_unique<RareData>();
     182        m_rareData->m_captureGroupNames.swap(pattern.m_captureGroupNames);
     183        m_rareData->m_namedGroupToParenIndex.swap(pattern.m_namedGroupToParenIndex);
    180184    }
    181185}
     
    195199    size_t regexDataSize = thisObject->m_regExpBytecode ? thisObject->m_regExpBytecode->estimatedSizeInBytes() : 0;
    196200#if ENABLE(YARR_JIT)
    197     regexDataSize += thisObject->m_regExpJITCode.size();
     201    if (auto* jitCode = thisObject->m_regExpJITCode.get())
     202        regexDataSize += jitCode->size();
    198203#endif
    199204    return Base::estimatedSize(cell, vm) + regexDataSize;
     
    238243void RegExp::compile(VM* vm, Yarr::YarrCharSize charSize)
    239244{
    240     ConcurrentJSLocker locker(m_lock);
     245    auto locker = holdLock(cellLock());
    241246   
    242247    Yarr::YarrPattern pattern(m_patternString, m_flags, m_constructionErrorCode, vm->stackLimit());
     
    259264#endif
    260265        ) {
    261         Yarr::jitCompile(pattern, m_patternString, charSize, vm, m_regExpJITCode);
    262         if (!m_regExpJITCode.failureReason()) {
     266        auto& jitCode = ensureRegExpJITCode();
     267        Yarr::jitCompile(pattern, m_patternString, charSize, vm, jitCode);
     268        if (!jitCode.failureReason()) {
    263269            m_state = JITCode;
    264270            return;
     
    284290    VM& vm, const String& s, unsigned startOffset, int& position, Vector<int>& ovector)
    285291{
    286     ConcurrentJSLocker locker(m_lock);
     292    auto locker = holdLock(cellLock());
    287293
    288294    if (!hasCodeFor(s.is8Bit() ? Yarr::Char8 : Yarr::Char16))
     
    295301void RegExp::compileMatchOnly(VM* vm, Yarr::YarrCharSize charSize)
    296302{
    297     ConcurrentJSLocker locker(m_lock);
     303    auto locker = holdLock(cellLock());
    298304   
    299305    Yarr::YarrPattern pattern(m_patternString, m_flags, m_constructionErrorCode, vm->stackLimit());
     
    316322#endif
    317323        ) {
    318         Yarr::jitCompile(pattern, m_patternString, charSize, vm, m_regExpJITCode, Yarr::MatchOnly);
    319         if (!m_regExpJITCode.failureReason()) {
     324        auto& jitCode = ensureRegExpJITCode();
     325        Yarr::jitCompile(pattern, m_patternString, charSize, vm, jitCode, Yarr::MatchOnly);
     326        if (!jitCode.failureReason()) {
    320327            m_state = JITCode;
    321328            return;
     
    340347bool RegExp::matchConcurrently(VM& vm, const String& s, unsigned startOffset, MatchResult& result)
    341348{
    342     ConcurrentJSLocker locker(m_lock);
     349    auto locker = holdLock(cellLock());
    343350
    344351    if (!hasMatchOnlyCodeFor(s.is8Bit() ? Yarr::Char8 : Yarr::Char16))
     
    351358void RegExp::deleteCode()
    352359{
    353     ConcurrentJSLocker locker(m_lock);
     360    auto locker = holdLock(cellLock());
    354361   
    355362    if (!hasCode())
     
    357364    m_state = NotCompiled;
    358365#if ENABLE(YARR_JIT)
    359     m_regExpJITCode.clear();
     366    if (m_regExpJITCode)
     367        m_regExpJITCode->clear();
    360368#endif
    361369    m_regExpBytecode = nullptr;
     
    427435
    428436#if ENABLE(YARR_JIT)
    429         Yarr::YarrCodeBlock& codeBlock = m_regExpJITCode;
    430 
    431437        const size_t jitAddrSize = 20;
    432         char jit8BitMatchOnlyAddr[jitAddrSize];
    433         char jit16BitMatchOnlyAddr[jitAddrSize];
    434         char jit8BitMatchAddr[jitAddrSize];
    435         char jit16BitMatchAddr[jitAddrSize];
    436         if (m_state == ByteCode) {
     438        char jit8BitMatchOnlyAddr[jitAddrSize] { };
     439        char jit16BitMatchOnlyAddr[jitAddrSize] { };
     440        char jit8BitMatchAddr[jitAddrSize] { };
     441        char jit16BitMatchAddr[jitAddrSize] { };
     442        switch (m_state) {
     443        case ParseError:
     444        case NotCompiled:
     445            break;
     446        case ByteCode:
    437447            snprintf(jit8BitMatchOnlyAddr, jitAddrSize, "fallback    ");
    438448            snprintf(jit16BitMatchOnlyAddr, jitAddrSize, "----      ");
    439449            snprintf(jit8BitMatchAddr, jitAddrSize, "fallback    ");
    440450            snprintf(jit16BitMatchAddr, jitAddrSize, "----      ");
    441         } else {
     451            break;
     452        case JITCode: {
     453            Yarr::YarrCodeBlock& codeBlock = *m_regExpJITCode.get();
    442454            snprintf(jit8BitMatchOnlyAddr, jitAddrSize, "0x%014lx", reinterpret_cast<uintptr_t>(codeBlock.get8BitMatchOnlyAddr()));
    443455            snprintf(jit16BitMatchOnlyAddr, jitAddrSize, "0x%014lx", reinterpret_cast<uintptr_t>(codeBlock.get16BitMatchOnlyAddr()));
    444456            snprintf(jit8BitMatchAddr, jitAddrSize, "0x%014lx", reinterpret_cast<uintptr_t>(codeBlock.get8BitMatchAddr()));
    445457            snprintf(jit16BitMatchAddr, jitAddrSize, "0x%014lx", reinterpret_cast<uintptr_t>(codeBlock.get16BitMatchAddr()));
     458            break;
     459        }
    446460        }
    447461#else
  • trunk/Source/JavaScriptCore/runtime/RegExp.h

    r242955 r243408  
    8989    bool hasNamedCaptures()
    9090    {
    91         return !m_captureGroupNames.isEmpty();
     91        return m_rareData && !m_rareData->m_captureGroupNames.isEmpty();
    9292    }
    9393
    9494    String getCaptureGroupName(unsigned i)
    9595    {
    96         if (!i || m_captureGroupNames.size() <= i)
     96        if (!i || !m_rareData || m_rareData->m_captureGroupNames.size() <= i)
    9797            return String();
    98         return m_captureGroupNames[i];
     98        ASSERT(m_rareData);
     99        return m_rareData->m_captureGroupNames[i];
    99100    }
    100101
    101102    unsigned subpatternForName(String groupName)
    102103    {
    103         auto it = m_namedGroupToParenIndex.find(groupName);
    104         if (it == m_namedGroupToParenIndex.end())
     104        if (!m_rareData)
     105            return 0;
     106        auto it = m_rareData->m_namedGroupToParenIndex.find(groupName);
     107        if (it == m_rareData->m_namedGroupToParenIndex.end())
    105108            return 0;
    106109        return it->value;
     
    158161#endif
    159162
     163#if ENABLE(YARR_JIT)
     164    Yarr::YarrCodeBlock& ensureRegExpJITCode()
     165    {
     166        if (!m_regExpJITCode)
     167            m_regExpJITCode = std::make_unique<Yarr::YarrCodeBlock>();
     168        return *m_regExpJITCode.get();
     169    }
     170#endif
     171
     172    struct RareData {
     173        WTF_MAKE_STRUCT_FAST_ALLOCATED;
     174        Vector<String> m_captureGroupNames;
     175        HashMap<String, unsigned> m_namedGroupToParenIndex;
     176    };
     177
    160178    String m_patternString;
    161179    RegExpState m_state { NotCompiled };
    162180    OptionSet<Yarr::Flags> m_flags;
    163     ConcurrentJSLock m_lock;
    164181    Yarr::ErrorCode m_constructionErrorCode { Yarr::ErrorCode::NoError };
    165182    unsigned m_numSubpatterns { 0 };
    166     Vector<String> m_captureGroupNames;
    167     HashMap<String, unsigned> m_namedGroupToParenIndex;
    168183    std::unique_ptr<Yarr::BytecodePattern> m_regExpBytecode;
     184#if ENABLE(YARR_JIT)
     185    std::unique_ptr<Yarr::YarrCodeBlock> m_regExpJITCode;
     186#endif
     187    std::unique_ptr<RareData> m_rareData;
    169188#if ENABLE(REGEXP_TRACING)
    170189    double m_rtMatchOnlyTotalSubjectStringLen { 0.0 };
     
    175194    unsigned m_rtMatchFoundCount { 0 };
    176195#endif
    177 
    178 #if ENABLE(YARR_JIT)
    179     Yarr::YarrCodeBlock m_regExpJITCode;
    180 #endif
    181196};
    182197
  • trunk/Source/JavaScriptCore/runtime/RegExpInlines.h

    r237763 r243408  
    7474        if (m_state != JITCode)
    7575            return true;
    76         if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode()))
    77             return true;
    78         if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode()))
     76        ASSERT(m_regExpJITCode);
     77        if ((charSize == Yarr::Char8) && (m_regExpJITCode->has8BitCode()))
     78            return true;
     79        if ((charSize == Yarr::Char16) && (m_regExpJITCode->has16BitCode()))
    7980            return true;
    8081#else
     
    157158    if (m_state == JITCode) {
    158159        {
     160            ASSERT(m_regExpJITCode);
    159161#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
    160             PatternContextBufferHolder patternContextBufferHolder(vm, m_regExpJITCode.usesPatternContextBuffer());
     162            PatternContextBufferHolder patternContextBufferHolder(vm, m_regExpJITCode->usesPatternContextBuffer());
    161163
    162164#define EXTRA_JIT_PARAMS  , patternContextBufferHolder.buffer(), patternContextBufferHolder.size()
     
    166168
    167169            if (s.is8Bit())
    168                 result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector EXTRA_JIT_PARAMS).start;
     170                result = m_regExpJITCode->execute(s.characters8(), startOffset, s.length(), offsetVector EXTRA_JIT_PARAMS).start;
    169171            else
    170                 result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector EXTRA_JIT_PARAMS).start;
     172                result = m_regExpJITCode->execute(s.characters16(), startOffset, s.length(), offsetVector EXTRA_JIT_PARAMS).start;
    171173
    172174#undef EXTRA_JIT_PARAMS
     
    231233        if (m_state != JITCode)
    232234            return true;
    233         if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCodeMatchOnly()))
    234             return true;
    235         if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCodeMatchOnly()))
     235        ASSERT(m_regExpJITCode);
     236        if ((charSize == Yarr::Char8) && (m_regExpJITCode->has8BitCodeMatchOnly()))
     237            return true;
     238        if ((charSize == Yarr::Char16) && (m_regExpJITCode->has16BitCodeMatchOnly()))
    236239            return true;
    237240#else
     
    278281    if (m_state == JITCode) {
    279282        {
     283            ASSERT(m_regExpJITCode);
    280284#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
    281             PatternContextBufferHolder patternContextBufferHolder(vm, m_regExpJITCode.usesPatternContextBuffer());
     285            PatternContextBufferHolder patternContextBufferHolder(vm, m_regExpJITCode->usesPatternContextBuffer());
    282286
    283287#define EXTRA_JIT_PARAMS  , patternContextBufferHolder.buffer(), patternContextBufferHolder.size()
     
    287291
    288292            if (s.is8Bit())
    289                 result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length() EXTRA_JIT_PARAMS);
     293                result = m_regExpJITCode->execute(s.characters8(), startOffset, s.length() EXTRA_JIT_PARAMS);
    290294            else
    291                 result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length() EXTRA_JIT_PARAMS);
     295                result = m_regExpJITCode->execute(s.characters16(), startOffset, s.length() EXTRA_JIT_PARAMS);
    292296
    293297#undef EXTRA_JIT_PARAMS
Note: See TracChangeset for help on using the changeset viewer.