Ignore:
Timestamp:
Mar 8, 2016, 1:15:07 PM (9 years ago)
Author:
[email protected]
Message:

Regexp matching should incur less call overhead
https://bugs.webkit.org/show_bug.cgi?id=155181

Reviewed by Geoffrey Garen.

Previously we had DFG/FTL code call into the DFGOperation, which then called in to
RegExpObject, which then called into createRegExpMatchesArray, which then called into
RegExp, which then called the code generated by Yarr.

Now we have DFG/FTL code call into the DFGOperation, which does all of the things and calls
into code generated by Yarr.

This is another tiny Octane/regexp speed-up.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • dfg/DFGOperations.cpp:
  • runtime/RegExp.cpp:

(JSC::regExpFlags):
(JSC::RegExp::compile):
(JSC::RegExp::match):
(JSC::RegExp::compileMatchOnly):
(JSC::RegExp::deleteCode):
(JSC::RegExpFunctionalTestCollector::clearRegExp): Deleted.
(JSC::RegExp::compileIfNecessary): Deleted.
(JSC::RegExp::compileIfNecessaryMatchOnly): Deleted.

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

(JSC::RegExpFunctionalTestCollector::clearRegExp):
(JSC::RegExp::compileIfNecessary):
(JSC::RegExp::matchInline):
(JSC::RegExp::compileIfNecessaryMatchOnly):

  • runtime/RegExpMatchesArray.cpp:

(JSC::createEmptyRegExpMatchesArray):
(JSC::createStructureImpl):
(JSC::tryCreateUninitializedRegExpMatchesArray): Deleted.
(JSC::createRegExpMatchesArray): Deleted.

  • runtime/RegExpMatchesArray.h:

(JSC::tryCreateUninitializedRegExpMatchesArray):
(JSC::createRegExpMatchesArray):

  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::put):
(JSC::RegExpObject::exec):
(JSC::RegExpObject::match):
(JSC::getLastIndexAsUnsigned): Deleted.

  • runtime/RegExpObject.h:

(JSC::RegExpObject::getLastIndex):
(JSC::RegExpObject::test):
(JSC::RegExpObject::testInline):

  • runtime/RegExpObjectInlines.h: Added.

(JSC::getRegExpObjectLastIndexAsUnsigned):
(JSC::RegExpObject::execInline):
(JSC::RegExpObject::matchInline):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/RegExp.cpp

    r197426 r197796  
    11/*
    22 *  Copyright (C) 1999-2001, 2004 Harri Porten ([email protected])
    3  *  Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
     3 *  Copyright (c) 2007, 2008, 2016 Apple Inc. All rights reserved.
    44 *  Copyright (C) 2009 Torch Mobile, Inc.
    55 *  Copyright (C) 2010 Peter Varga ([email protected]), University of Szeged
     
    2727#include "JSCInlines.h"
    2828#include "RegExpCache.h"
     29#include "RegExpInlines.h"
    2930#include "Yarr.h"
    3031#include "YarrJIT.h"
    3132#include <wtf/Assertions.h>
    32 
    33 #define REGEXP_FUNC_TEST_DATA_GEN 0
    34 
    35 #if REGEXP_FUNC_TEST_DATA_GEN
    36 #include <stdio.h>
    37 #include <stdlib.h>
    38 #include <string.h>
    39 #endif
    4033
    4134namespace JSC {
     
    8275
    8376#if REGEXP_FUNC_TEST_DATA_GEN
    84 class RegExpFunctionalTestCollector {
    85     // This class is not thread safe.
    86 protected:
    87     static const char* const s_fileName;
    88 
    89 public:
    90     static RegExpFunctionalTestCollector* get();
    91 
    92     ~RegExpFunctionalTestCollector();
    93 
    94     void outputOneTest(RegExp*, String, int, int*, int);
    95     void clearRegExp(RegExp* regExp)
    96     {
    97         if (regExp == m_lastRegExp)
    98             m_lastRegExp = 0;
    99     }
    100 
    101 private:
    102     RegExpFunctionalTestCollector();
    103 
    104     void outputEscapedString(const String&, bool escapeSlash = false);
    105 
    106     static RegExpFunctionalTestCollector* s_instance;
    107     FILE* m_file;
    108     RegExp* m_lastRegExp;
    109 };
    110 
    11177const char* const RegExpFunctionalTestCollector::s_fileName = "/tmp/RegExpTestsData";
    11278RegExpFunctionalTestCollector* RegExpFunctionalTestCollector::s_instance = 0;
     
    321287}
    322288
    323 void RegExp::compileIfNecessary(VM& vm, Yarr::YarrCharSize charSize)
    324 {
    325     if (hasCode()) {
    326 #if ENABLE(YARR_JIT)
    327         if (m_state != JITCode)
    328             return;
    329         if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode()))
    330             return;
    331         if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode()))
    332             return;
    333 #else
    334         return;
    335 #endif
    336     }
    337 
    338     compile(&vm, charSize);
    339 }
    340 
    341289int RegExp::match(VM& vm, const String& s, unsigned startOffset, Vector<int, 32>& ovector)
    342290{
    343 #if ENABLE(REGEXP_TRACING)
    344     m_rtMatchCallCount++;
    345     m_rtMatchTotalSubjectStringLen += (double)(s.length() - startOffset);
    346 #endif
    347 
    348     ASSERT(m_state != ParseError);
    349     compileIfNecessary(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
    350 
    351     int offsetVectorSize = (m_numSubpatterns + 1) * 2;
    352     ovector.resize(offsetVectorSize);
    353     int* offsetVector = ovector.data();
    354 
    355     int result;
    356 #if ENABLE(YARR_JIT)
    357     if (m_state == JITCode) {
    358         if (s.is8Bit())
    359             result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start;
    360         else
    361             result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector).start;
    362 #if ENABLE(YARR_JIT_DEBUG)
    363         matchCompareWithInterpreter(s, startOffset, offsetVector, result);
    364 #endif
    365     } else
    366 #endif
    367         result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
    368 
    369     // FIXME: The YARR engine should handle unsigned or size_t length matches.
    370     // The YARR Interpreter is "unsigned" clean, while the YARR JIT hasn't been addressed.
    371     // The offset vector handling needs to change as well.
    372     // Right now we convert a match where the offsets overflowed into match failure.
    373     // There are two places in WebCore that call the interpreter directly that need to
    374     // have their offsets changed to int as well. They are yarr/RegularExpression.cpp
    375     // and inspector/ContentSearchUtilities.cpp
    376     if (s.length() > INT_MAX) {
    377         bool overflowed = false;
    378 
    379         if (result < -1)
    380             overflowed = true;
    381 
    382         for (unsigned i = 0; i <= m_numSubpatterns; i++) {
    383             if ((offsetVector[i*2] < -1) || ((offsetVector[i*2] >= 0) && (offsetVector[i*2+1] < -1))) {
    384                 overflowed = true;
    385                 offsetVector[i*2] = -1;
    386                 offsetVector[i*2+1] = -1;
    387             }
    388         }
    389 
    390         if (overflowed)
    391             result = -1;
    392     }
    393 
    394     ASSERT(result >= -1);
    395 
    396 #if REGEXP_FUNC_TEST_DATA_GEN
    397     RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
    398 #endif
    399 
    400 #if ENABLE(REGEXP_TRACING)
    401     if (result != -1)
    402         m_rtMatchFoundCount++;
    403 #endif
    404 
    405     return result;
     291    return matchInline(vm, s, startOffset, ovector);
    406292}
    407293
     
    440326}
    441327
    442 void RegExp::compileIfNecessaryMatchOnly(VM& vm, Yarr::YarrCharSize charSize)
    443 {
    444     if (hasCode()) {
    445 #if ENABLE(YARR_JIT)
    446         if (m_state != JITCode)
    447             return;
    448         if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCodeMatchOnly()))
    449             return;
    450         if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCodeMatchOnly()))
    451             return;
    452 #else
    453         return;
    454 #endif
    455     }
    456 
    457     compileMatchOnly(&vm, charSize);
    458 }
    459 
    460328MatchResult RegExp::match(VM& vm, const String& s, unsigned startOffset)
    461329{
    462 #if ENABLE(REGEXP_TRACING)
    463     m_rtMatchOnlyCallCount++;
    464     m_rtMatchOnlyTotalSubjectStringLen += (double)(s.length() - startOffset);
    465 #endif
    466 
    467     ASSERT(m_state != ParseError);
    468     compileIfNecessaryMatchOnly(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
    469 
    470 #if ENABLE(YARR_JIT)
    471     if (m_state == JITCode) {
    472         MatchResult result = s.is8Bit() ?
    473             m_regExpJITCode.execute(s.characters8(), startOffset, s.length()) :
    474             m_regExpJITCode.execute(s.characters16(), startOffset, s.length());
    475 #if ENABLE(REGEXP_TRACING)
    476         if (!result)
    477             m_rtMatchOnlyFoundCount++;
    478 #endif
    479         return result;
    480     }
    481 #endif
    482 
    483     int offsetVectorSize = (m_numSubpatterns + 1) * 2;
    484     int* offsetVector;
    485     Vector<int, 32> nonReturnedOvector;
    486     nonReturnedOvector.resize(offsetVectorSize);
    487     offsetVector = nonReturnedOvector.data();
    488     int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
    489 #if REGEXP_FUNC_TEST_DATA_GEN
    490     RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
    491 #endif
    492 
    493     if (r >= 0) {
    494 #if ENABLE(REGEXP_TRACING)
    495         m_rtMatchOnlyFoundCount++;
    496 #endif
    497         return MatchResult(r, reinterpret_cast<unsigned*>(offsetVector)[1]);
    498     }
    499 
    500     return MatchResult::failed();
     330    return matchInline(vm, s, startOffset);
    501331}
    502332
Note: See TracChangeset for help on using the changeset viewer.