Ignore:
Timestamp:
Mar 28, 2012, 3:18:20 PM (13 years ago)
Author:
[email protected]
Message:

Yarr: if we're not using the output array, don't populate it!
https://bugs.webkit.org/show_bug.cgi?id=82519

Reviewed by Sam Weinig.

../JavaScriptCore:

Add a new variant of the match method to RegExp that returns a MatchResult,
and modify YarrJIT to be able to compile code that doesn't use an output vector.

This is a 3% progression on v8-regexp.

  • JavaScriptCore.xcodeproj/project.pbxproj:
    • Moved MatchResult into its own header.
  • assembler/AbstractMacroAssembler.h:
    • Added missing include.
  • runtime/MatchResult.h: Added.

(MatchResult::MatchResult):
(MatchResult):
(MatchResult::failed):
(MatchResult::operator bool):
(MatchResult::empty):

  • Moved MatchResult into its own header.
  • runtime/RegExp.cpp:

(JSC::RegExp::compile):
(JSC::RegExp::compileIfNecessary):
(JSC::RegExp::match):

  • Changed due to execute & representation changes.

(JSC::RegExp::compileMatchOnly):
(JSC::RegExp::compileIfNecessaryMatchOnly):

  • Added helper to compile MatchOnly code.

(JSC::RegExp::invalidateCode):
(JSC::RegExp::matchCompareWithInterpreter):
(JSC::RegExp::printTraceData):

  • Changed due representation changes.
  • runtime/RegExp.h:

(RegExp):
(JSC::RegExp::hasCode):

  • Made YarrCodeBlock a member.
  • runtime/RegExpConstructor.h:

(RegExpConstructor):
(JSC::RegExpConstructor::performMatch):

  • Added no-ovector form.
  • runtime/RegExpMatchesArray.cpp:

(JSC::RegExpMatchesArray::reifyAllProperties):

  • Match now takes a reference to ovector, not a pointer.
  • runtime/RegExpObject.h:

(JSC):

  • Moved MatchResult into its own header.
  • runtime/StringPrototype.cpp:

(JSC::stringProtoFuncSplit):

  • Match now takes a reference to ovector, not a pointer.
  • testRegExp.cpp:

(testOneRegExp):

  • Match now takes a reference to ovector, not a pointer.
  • yarr/YarrJIT.cpp:

(Yarr):
(YarrGenerator):
(JSC::Yarr::YarrGenerator::initCallFrame):
(JSC::Yarr::YarrGenerator::removeCallFrame):
(JSC::Yarr::YarrGenerator::setSubpatternStart):
(JSC::Yarr::YarrGenerator::setSubpatternEnd):
(JSC::Yarr::YarrGenerator::clearSubpatternStart):
(JSC::Yarr::YarrGenerator::setMatchStart):
(JSC::Yarr::YarrGenerator::getMatchStart):

  • Added helper functions to intermediate access to output.

(JSC::Yarr::YarrGenerator::generateDotStarEnclosure):
(JSC::Yarr::YarrGenerator::generate):
(JSC::Yarr::YarrGenerator::backtrack):
(JSC::Yarr::YarrGenerator::generateEnter):
(JSC::Yarr::YarrGenerator::compile):

  • Changed to use the new helpers, only generate subpatterns if IncludeSubpatterns.

(JSC::Yarr::jitCompile):

  • Needs to template of MatchOnly or IncludeSubpatterns.
  • yarr/YarrJIT.h:

(YarrCodeBlock):
(JSC::Yarr::YarrCodeBlock::set8BitCode):
(JSC::Yarr::YarrCodeBlock::set16BitCode):
(JSC::Yarr::YarrCodeBlock::has8BitCodeMatchOnly):
(JSC::Yarr::YarrCodeBlock::has16BitCodeMatchOnly):
(JSC::Yarr::YarrCodeBlock::set8BitCodeMatchOnly):
(JSC::Yarr::YarrCodeBlock::set16BitCodeMatchOnly):
(JSC::Yarr::YarrCodeBlock::execute):
(JSC::Yarr::YarrCodeBlock::clear):

  • Added a second set of CodeRefs, so that we can compile RexExps with/without subpattern matching.

../WebCore:

  • ForwardingHeaders/runtime/MatchResult.h: Added.
  • ForwardingHeaders/yarr/YarrJIT.h: Added.
    • Added forwarding headers.
Location:
trunk/Source/JavaScriptCore/runtime
Files:
1 added
6 edited

Legend:

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

    r111889 r112454  
    219219
    220220struct RegExpRepresentation {
    221 #if ENABLE(YARR_JIT)
    222     Yarr::YarrCodeBlock m_regExpJITCode;
    223 #endif
    224     OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
    225221};
    226222
     
    280276    ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
    281277
    282     if (!m_representation) {
     278    if (!hasCode()) {
    283279        ASSERT(m_state == NotCompiled);
    284         m_representation = adoptPtr(new RegExpRepresentation);
    285280        globalData->regExpCache()->addToStrongCache(this);
    286281        m_state = ByteCode;
     
    289284#if ENABLE(YARR_JIT)
    290285    if (!pattern.m_containsBackreferences && globalData->canUseJIT()) {
    291         Yarr::jitCompile(pattern, charSize, globalData, m_representation->m_regExpJITCode);
     286        Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode);
    292287#if ENABLE(YARR_JIT_DEBUG)
    293         if (!m_representation->m_regExpJITCode.isFallBack())
     288        if (!m_regExpJITCode.isFallBack())
    294289            m_state = JITCode;
    295290        else
    296291            m_state = ByteCode;
    297292#else
    298         if (!m_representation->m_regExpJITCode.isFallBack()) {
     293        if (!m_regExpJITCode.isFallBack()) {
    299294            m_state = JITCode;
    300295            return;
     
    306301#endif
    307302
    308     m_representation->m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
     303    m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
    309304}
    310305
    311306void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize charSize)
    312307{
    313     // If the state is NotCompiled or ParseError, then there is no representation.
    314     // If there is a representation, and the state must be either JITCode or ByteCode.
    315     ASSERT(!!m_representation == (m_state == JITCode || m_state == ByteCode));
    316    
    317     if (m_representation) {
     308    if (hasCode()) {
    318309#if ENABLE(YARR_JIT)
    319310        if (m_state != JITCode)
    320311            return;
    321         if ((charSize == Yarr::Char8) && (m_representation->m_regExpJITCode.has8BitCode()))
    322             return;
    323         if ((charSize == Yarr::Char16) && (m_representation->m_regExpJITCode.has16BitCode()))
     312        if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode()))
     313            return;
     314        if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode()))
    324315            return;
    325316#else
     
    331322}
    332323
    333 int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>* ovector)
     324int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>& ovector)
    334325{
    335326#if ENABLE(REGEXP_TRACING)
     
    341332
    342333    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
    343     int* offsetVector;
    344     Vector<int, 32> nonReturnedOvector;
    345     if (ovector) {
    346         ovector->resize(offsetVectorSize);
    347         offsetVector = ovector->data();
    348     } else {
    349         nonReturnedOvector.resize(offsetVectorSize);
    350         offsetVector = nonReturnedOvector.data();
    351     }
    352     ASSERT(offsetVector);
     334    ovector.resize(offsetVectorSize);
     335    int* offsetVector = ovector.data();
    353336
    354337    int result;
     
    356339    if (m_state == JITCode) {
    357340        if (s.is8Bit())
    358             result = Yarr::execute(m_representation->m_regExpJITCode, s.characters8(), startOffset, s.length(), offsetVector);
     341            result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start;
    359342        else
    360             result = Yarr::execute(m_representation->m_regExpJITCode, s.characters16(), startOffset, s.length(), offsetVector);
     343            result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector).start;
    361344#if ENABLE(YARR_JIT_DEBUG)
    362345        matchCompareWithInterpreter(s, startOffset, offsetVector, result);
     
    364347    } else
    365348#endif
    366         result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), reinterpret_cast<unsigned*>(offsetVector));
     349        result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, s.length(), reinterpret_cast<unsigned*>(offsetVector));
    367350
    368351    // FIXME: The YARR engine should handle unsigned or size_t length matches.
     
    405388}
    406389
     390void RegExp::compileMatchOnly(JSGlobalData* globalData, Yarr::YarrCharSize charSize)
     391{
     392    Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
     393    if (m_constructionError) {
     394        ASSERT_NOT_REACHED();
     395        m_state = ParseError;
     396        return;
     397    }
     398    ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
     399
     400    if (!hasCode()) {
     401        ASSERT(m_state == NotCompiled);
     402        globalData->regExpCache()->addToStrongCache(this);
     403        m_state = ByteCode;
     404    }
     405
     406#if ENABLE(YARR_JIT)
     407    if (!pattern.m_containsBackreferences && globalData->canUseJIT()) {
     408        Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode, Yarr::MatchOnly);
     409#if ENABLE(YARR_JIT_DEBUG)
     410        if (!m_regExpJITCode.isFallBack())
     411            m_state = JITCode;
     412        else
     413            m_state = ByteCode;
     414#else
     415        if (!m_regExpJITCode.isFallBack()) {
     416            m_state = JITCode;
     417            return;
     418        }
     419#endif
     420    }
     421#else
     422    UNUSED_PARAM(charSize);
     423#endif
     424
     425    m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
     426}
     427
     428void RegExp::compileIfNecessaryMatchOnly(JSGlobalData& globalData, Yarr::YarrCharSize charSize)
     429{
     430    if (hasCode()) {
     431#if ENABLE(YARR_JIT)
     432        if (m_state != JITCode)
     433            return;
     434        if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCodeMatchOnly()))
     435            return;
     436        if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCodeMatchOnly()))
     437            return;
     438#else
     439        return;
     440#endif
     441    }
     442
     443    compileMatchOnly(&globalData, charSize);
     444}
     445
     446MatchResult RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset)
     447{
     448#if ENABLE(REGEXP_TRACING)
     449    m_rtMatchCallCount++;
     450#endif
     451
     452    ASSERT(m_state != ParseError);
     453    compileIfNecessaryMatchOnly(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
     454
     455#if ENABLE(YARR_JIT)
     456    if (m_state == JITCode) {
     457        MatchResult result = s.is8Bit() ?
     458            m_regExpJITCode.execute(s.characters8(), startOffset, s.length()) :
     459            m_regExpJITCode.execute(s.characters16(), startOffset, s.length());
     460#if ENABLE(REGEXP_TRACING)
     461        if (!result)
     462            m_rtMatchFoundCount++;
     463#endif
     464        return result;
     465    }
     466#endif
     467
     468    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
     469    int* offsetVector;
     470    Vector<int, 32> nonReturnedOvector;
     471    nonReturnedOvector.resize(offsetVectorSize);
     472    offsetVector = nonReturnedOvector.data();
     473    int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, s.length(), reinterpret_cast<unsigned*>(offsetVector));
     474#if REGEXP_FUNC_TEST_DATA_GEN
     475    RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
     476#endif
     477
     478    if (r >= 0) {
     479#if ENABLE(REGEXP_TRACING)
     480        m_rtMatchFoundCount++;
     481#endif
     482        return MatchResult(r, reinterpret_cast<unsigned*>(offsetVector)[1]);
     483    }
     484
     485    return MatchResult::failed();
     486}
     487
    407488void RegExp::invalidateCode()
    408489{
    409     if (!m_representation)
     490    if (!hasCode())
    410491        return;
    411492    m_state = NotCompiled;
    412     m_representation.clear();
     493    m_regExpJITCode.clear();
     494    m_regExpBytecode.clear();
    413495}
    414496
     
    429511        interpreterOffsetVector[j] = -1;
    430512
    431     interpreterResult = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), interpreterOffsetVector);
     513    interpreterResult = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, s.length(), interpreterOffsetVector);
    432514
    433515    if (jitResult != interpreterResult)
     
    478560
    479561#if ENABLE(YARR_JIT)
    480         Yarr::YarrCodeBlock& codeBlock = m_representation->m_regExpJITCode;
     562        Yarr::YarrCodeBlock& codeBlock = m_regExpJITCode;
    481563
    482564        const size_t jitAddrSize = 20;
  • trunk/Source/JavaScriptCore/runtime/RegExp.h

    r106189 r112454  
    2323#define RegExp_h
    2424
     25#include "ExecutableAllocator.h"
     26#include "MatchResult.h"
     27#include "RegExpKey.h"
     28#include "Structure.h"
    2529#include "UString.h"
    26 #include "ExecutableAllocator.h"
    27 #include "Structure.h"
    28 #include "RegExpKey.h"
    2930#include "yarr/Yarr.h"
    3031#include <wtf/Forward.h>
    3132#include <wtf/RefCounted.h>
     33
     34#if ENABLE(YARR_JIT)
     35#include "yarr/YarrJIT.h"
     36#endif
    3237
    3338namespace JSC {
     
    5459        const char* errorMessage() const { return m_constructionError; }
    5560
    56         JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>* ovector = 0);
     61        JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>& ovector);
     62        MatchResult match(JSGlobalData&, const UString&, unsigned startOffset);
    5763        unsigned numSubpatterns() const { return m_numSubpatterns; }
    5864
    5965        bool hasCode()
    6066        {
    61             return m_representation;
     67            return m_state != NotCompiled;
    6268        }
    6369
     
    96102        void compileIfNecessary(JSGlobalData&, Yarr::YarrCharSize);
    97103
     104        void compileMatchOnly(JSGlobalData*, Yarr::YarrCharSize);
     105        void compileIfNecessaryMatchOnly(JSGlobalData&, Yarr::YarrCharSize);
     106
    98107#if ENABLE(YARR_JIT_DEBUG)
    99108        void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult);
     
    109118#endif
    110119
    111         OwnPtr<RegExpRepresentation> m_representation;
     120#if ENABLE(YARR_JIT)
     121        Yarr::YarrCodeBlock m_regExpJITCode;
     122#endif
     123        OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
    112124    };
    113125
  • trunk/Source/JavaScriptCore/runtime/RegExpConstructor.h

    r111889 r112454  
    5656        static const ClassInfo s_info;
    5757
    58         MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset, int** ovector = 0);
     58        MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset, int** ovector);
     59        MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset);
    5960
    6061        void setMultiline(bool multiline) { m_multiline = multiline; }
     
    103104    ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset, int** ovector)
    104105    {
    105         int position = regExp->match(globalData, input, startOffset, &m_ovector);
     106        int position = regExp->match(globalData, input, startOffset, m_ovector);
    106107
    107108        if (ovector)
     
    120121        return MatchResult(position, end);
    121122    }
     123    ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset)
     124    {
     125        MatchResult result = regExp->match(globalData, input, startOffset);
     126        if (result)
     127            m_cachedResult.record(globalData, this, regExp, string, result);
     128        return result;
     129    }
    122130
    123131} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp

    r111889 r112454  
    5959    if (unsigned numSubpatterns = m_regExp->numSubpatterns()) {
    6060        Vector<int, 32> subpatternResults;
    61         int position = m_regExp->match(exec->globalData(), m_input->value(exec), m_result.start, &subpatternResults);
     61        int position = m_regExp->match(exec->globalData(), m_input->value(exec), m_result.start, subpatternResults);
    6262        ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == m_result.start);
    6363        ASSERT(m_result.start == static_cast<size_t>(subpatternResults[0]));
  • trunk/Source/JavaScriptCore/runtime/RegExpObject.h

    r111603 r112454  
    2626
    2727namespace JSC {
    28    
    29     struct MatchResult {
    30         ALWAYS_INLINE MatchResult(size_t start, size_t end)
    31             : start(start)
    32             , end(end)
    33         {
    34         }
    35         ALWAYS_INLINE static MatchResult failed()
    36         {
    37             return MatchResult(WTF::notFound, 0);
    38         }
    39         ALWAYS_INLINE operator bool()
    40         {
    41             return start != WTF::notFound;
    42         }
    43         ALWAYS_INLINE bool empty()
    44         {
    45             return start == end;
    46         }
    47         size_t start;
    48         size_t end;
    49     };
    5028   
    5129    class RegExpObject : public JSNonFinalObject {
  • trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp

    r111889 r112454  
    964964            //    Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
    965965            // d. Return A.
    966             if (reg->match(*globalData, input, 0) < 0)
     966            if (!reg->match(*globalData, input, 0))
    967967                result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
    968968            return JSValue::encode(result);
     
    975975            // a. Call SplitMatch(S, q, R) and let z be its MatchResult result.
    976976            Vector<int, 32> ovector;
    977             int mpos = reg->match(*globalData, input, matchPosition, &ovector);
     977            int mpos = reg->match(*globalData, input, matchPosition, ovector);
    978978            // b. If z is failure, then let q = q + 1.
    979979            if (mpos < 0)
Note: See TracChangeset for help on using the changeset viewer.