Changeset 73307 in webkit


Ignore:
Timestamp:
Dec 3, 2010 2:48:19 PM (13 years ago)
Author:
msaboff@apple.com
Message:

2010-12-03 Michael Saboff <msaboff@apple.com>

Reviewed by Gavin Barraclough

Changes to significantly reduce branches to branches in JIT'ed
parentheses backtrack processing. The changes include the following:

  • Taking the backtracking processing out of line and adding it as code at the end of the JIT'ed routine.
  • Allow backtracks to be direct via an indirect branch for an address pushed onto the stack. If the use of an indirect branch is from a conditional jump, then we emit a trampoline at the end of the routine.
  • Propogate backtracks instead of adding trampolines. Backtracks are propogated to where they are used. This change also eliminated trampoline branch code that aren't used.
  • Added global expression state to keep track of parentheses tail code and indirect branches. Other changes made to support these changes.
  • Split invertOrCapture flag on Patterns to two separate flags. Added getters for these flags. Rippled these changes to both the JIT and interpreter code.
  • Split BacktrackDestination out off TermGenerationState struct. This is done to hold references to a backtrack for later code generation. https://bugs.webkit.org/show_bug.cgi?id=50295
  • assembler/ARMAssembler.h: (JSC::ARMAssembler::JmpDst::isSet):
  • assembler/ARMv7Assembler.h: (JSC::ARMv7Assembler::JmpDst::isSet):
  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::Label::isSet): (JSC::AbstractMacroAssembler::DataLabelPtr::isUsed): (JSC::AbstractMacroAssembler::DataLabelPtr::used): (JSC::AbstractMacroAssembler::JumpList::clear):
  • assembler/MIPSAssembler.h: (JSC::MIPSAssembler::JmpDst::isSet):
  • assembler/X86Assembler.h: (JSC::X86Assembler::JmpDst::isSet):
  • yarr/RegexCompiler.cpp: (JSC::Yarr::RegexPatternConstructor::atomParenthesesSubpatternBegin): (JSC::Yarr::RegexPatternConstructor::atomParentheticalAssertionBegin): (JSC::Yarr::RegexPatternConstructor::atomBackReference): (JSC::Yarr::RegexPatternConstructor::setupAlternativeBeginTerms):
  • yarr/RegexInterpreter.cpp: (JSC::Yarr::ByteCompiler::atomParenthesesOnceBegin): (JSC::Yarr::ByteCompiler::atomParenthesesTerminalBegin): (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternBegin): (JSC::Yarr::ByteCompiler::atomParentheticalAssertionBegin): (JSC::Yarr::ByteCompiler::atomParentheticalAssertionEnd): (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternEnd): (JSC::Yarr::ByteCompiler::atomParenthesesOnceEnd): (JSC::Yarr::ByteCompiler::atomParenthesesTerminalEnd): (JSC::Yarr::ByteCompiler::emitDisjunction):
  • yarr/RegexInterpreter.h: (JSC::Yarr::ByteTerm::ByteTerm): (JSC::Yarr::ByteTerm::BackReference): (JSC::Yarr::ByteTerm::invert): (JSC::Yarr::ByteTerm::capture):
  • yarr/RegexJIT.cpp: (JSC::Yarr::RegexGenerator::IndirectJumpEntry::IndirectJumpEntry): (JSC::Yarr::RegexGenerator::IndirectJumpEntry::addJump): (JSC::Yarr::RegexGenerator::GenerationState::GenerationState): (JSC::Yarr::RegexGenerator::GenerationState::addIndirectJumpEntry): (JSC::Yarr::RegexGenerator::GenerationState::emitIndirectJumpTable): (JSC::Yarr::RegexGenerator::GenerationState::addParenthesesTail): (JSC::Yarr::RegexGenerator::GenerationState::emitParenthesesTail): (JSC::Yarr::RegexGenerator::GenerationState::addJumpToNextInteration): (JSC::Yarr::RegexGenerator::GenerationState::addJumpsToNextInteration): (JSC::Yarr::RegexGenerator::GenerationState::addDataLabelToNextIteration): (JSC::Yarr::RegexGenerator::GenerationState::linkToNextIteration): (JSC::Yarr::RegexGenerator::BacktrackDestination::BacktrackDestination): (JSC::Yarr::RegexGenerator::BacktrackDestination::clear): (JSC::Yarr::RegexGenerator::BacktrackDestination::clearDataLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::haveDestination): (JSC::Yarr::RegexGenerator::BacktrackDestination::isStackOffset): (JSC::Yarr::RegexGenerator::BacktrackDestination::isLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::isJumpList): (JSC::Yarr::RegexGenerator::BacktrackDestination::haveDataLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::copyTarget): (JSC::Yarr::RegexGenerator::BacktrackDestination::copyTo): (JSC::Yarr::RegexGenerator::BacktrackDestination::addBacktrackJump): (JSC::Yarr::RegexGenerator::BacktrackDestination::setStackOffset): (JSC::Yarr::RegexGenerator::BacktrackDestination::setLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::setNextBacktrackLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::setBacktrackToLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::setBacktrackJumpList): (JSC::Yarr::RegexGenerator::BacktrackDestination::setBacktrackSourceLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::setDataLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::setSubDataLabelPtr): (JSC::Yarr::RegexGenerator::BacktrackDestination::linkToNextBacktrack): (JSC::Yarr::RegexGenerator::BacktrackDestination::getStackOffset): (JSC::Yarr::RegexGenerator::BacktrackDestination::getLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::getBacktrackJumps): (JSC::Yarr::RegexGenerator::BacktrackDestination::getDataLabel): (JSC::Yarr::RegexGenerator::BacktrackDestination::jumpToBacktrack): (JSC::Yarr::RegexGenerator::BacktrackDestination::linkDataLabelToHereIfExists): (JSC::Yarr::RegexGenerator::BacktrackDestination::plantJumpToBacktrackIfExists): (JSC::Yarr::RegexGenerator::BacktrackDestination::linkAlternativeBacktracks): (JSC::Yarr::RegexGenerator::BacktrackDestination::linkAlternativeBacktracksTo): (JSC::Yarr::RegexGenerator::TermGenerationState::TermGenerationState): (JSC::Yarr::RegexGenerator::TermGenerationState::resetAlternative): (JSC::Yarr::RegexGenerator::TermGenerationState::isLastAlternative): (JSC::Yarr::RegexGenerator::TermGenerationState::clearBacktrack): (JSC::Yarr::RegexGenerator::TermGenerationState::jumpToBacktrack): (JSC::Yarr::RegexGenerator::TermGenerationState::plantJumpToBacktrackIfExists): (JSC::Yarr::RegexGenerator::TermGenerationState::linkDataLabelToBacktrackIfExists): (JSC::Yarr::RegexGenerator::TermGenerationState::addBacktrackJump): (JSC::Yarr::RegexGenerator::TermGenerationState::setDataLabelPtr): (JSC::Yarr::RegexGenerator::TermGenerationState::setBackTrackStackOffset): (JSC::Yarr::RegexGenerator::TermGenerationState::setBacktrackLabel): (JSC::Yarr::RegexGenerator::TermGenerationState::linkAlternativeBacktracks): (JSC::Yarr::RegexGenerator::TermGenerationState::linkAlternativeBacktracksTo): (JSC::Yarr::RegexGenerator::TermGenerationState::setBacktrackLink): (JSC::Yarr::RegexGenerator::TermGenerationState::chainBacktracks): (JSC::Yarr::RegexGenerator::TermGenerationState::chainBacktrackJumps): (JSC::Yarr::RegexGenerator::TermGenerationState::getBacktrackDestination): (JSC::Yarr::RegexGenerator::TermGenerationState::propagateBacktrackingFrom): (JSC::Yarr::RegexGenerator::ParenthesesTail::ParenthesesTail): (JSC::Yarr::RegexGenerator::ParenthesesTail::processBacktracks): (JSC::Yarr::RegexGenerator::ParenthesesTail::setNextIteration): (JSC::Yarr::RegexGenerator::ParenthesesTail::generateCode): (JSC::Yarr::RegexGenerator::generateAssertionBOL): (JSC::Yarr::RegexGenerator::generateAssertionEOL): (JSC::Yarr::RegexGenerator::generateAssertionWordBoundary): (JSC::Yarr::RegexGenerator::generatePatternCharacterSingle): (JSC::Yarr::RegexGenerator::generatePatternCharacterPair): (JSC::Yarr::RegexGenerator::generatePatternCharacterFixed): (JSC::Yarr::RegexGenerator::generatePatternCharacterGreedy): (JSC::Yarr::RegexGenerator::generatePatternCharacterNonGreedy): (JSC::Yarr::RegexGenerator::generateCharacterClassSingle): (JSC::Yarr::RegexGenerator::generateCharacterClassFixed): (JSC::Yarr::RegexGenerator::generateCharacterClassGreedy): (JSC::Yarr::RegexGenerator::generateCharacterClassNonGreedy): (JSC::Yarr::RegexGenerator::generateParenthesesDisjunction): (JSC::Yarr::RegexGenerator::generateParenthesesSingle): (JSC::Yarr::RegexGenerator::generateParenthesesGreedyNoBacktrack): (JSC::Yarr::RegexGenerator::generateParentheticalAssertion): (JSC::Yarr::RegexGenerator::generateDisjunction): (JSC::Yarr::RegexGenerator::compile):
  • yarr/RegexPattern.h: (JSC::Yarr::PatternTerm::PatternTerm): (JSC::Yarr::PatternTerm::invert): (JSC::Yarr::PatternTerm::capture):

2010-12-03 Michael Saboff <msaboff@apple.com>

Reviewed by Gavin Barraclough

Added new tests to support changes to Regexp JIT code handling
of parentheses. Tests focused on backtracking and nested
subexpressions.
https://bugs.webkit.org/show_bug.cgi?id=50295

  • fast/regex/parentheses-expected.txt: Added.
  • fast/regex/parentheses.html: Added.
  • fast/regex/script-tests/parentheses.js: Added.
Location:
trunk
Files:
3 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r73283 r73307  
     12010-12-03  Michael Saboff  <msaboff@apple.com>
     2
     3        Reviewed by Gavin Barraclough
     4
     5        Changes to significantly reduce branches to branches in JIT'ed
     6        parentheses backtrack processing.  The changes include the following:
     7        - Taking the backtracking processing out of line and adding it as
     8          code at the end of the JIT'ed routine.
     9        - Allow backtracks to be direct via an indirect branch for an address
     10          pushed onto the stack.  If the use of an indirect branch is from a
     11          conditional jump, then we emit a trampoline at the end of the
     12          routine.
     13        - Propogate backtracks instead of adding trampolines.  Backtracks are
     14          propogated to where they are used.  This change also eliminated
     15          trampoline branch code that aren't used.
     16        - Added global expression state to keep track of parentheses tail
     17          code and indirect branches.
     18        Other changes made to support these changes.
     19        - Split invertOrCapture flag on Patterns to two separate flags.  Added
     20          getters for these flags.  Rippled these changes to both the JIT
     21          and interpreter code.
     22        - Split BacktrackDestination out off TermGenerationState struct.
     23          This is done to hold references to a backtrack for later code
     24          generation.
     25        https://bugs.webkit.org/show_bug.cgi?id=50295
     26
     27        * assembler/ARMAssembler.h:
     28        (JSC::ARMAssembler::JmpDst::isSet):
     29        * assembler/ARMv7Assembler.h:
     30        (JSC::ARMv7Assembler::JmpDst::isSet):
     31        * assembler/AbstractMacroAssembler.h:
     32        (JSC::AbstractMacroAssembler::Label::isSet):
     33        (JSC::AbstractMacroAssembler::DataLabelPtr::isUsed):
     34        (JSC::AbstractMacroAssembler::DataLabelPtr::used):
     35        (JSC::AbstractMacroAssembler::JumpList::clear):
     36        * assembler/MIPSAssembler.h:
     37        (JSC::MIPSAssembler::JmpDst::isSet):
     38        * assembler/X86Assembler.h:
     39        (JSC::X86Assembler::JmpDst::isSet):
     40        * yarr/RegexCompiler.cpp:
     41        (JSC::Yarr::RegexPatternConstructor::atomParenthesesSubpatternBegin):
     42        (JSC::Yarr::RegexPatternConstructor::atomParentheticalAssertionBegin):
     43        (JSC::Yarr::RegexPatternConstructor::atomBackReference):
     44        (JSC::Yarr::RegexPatternConstructor::setupAlternativeBeginTerms):
     45        * yarr/RegexInterpreter.cpp:
     46        (JSC::Yarr::ByteCompiler::atomParenthesesOnceBegin):
     47        (JSC::Yarr::ByteCompiler::atomParenthesesTerminalBegin):
     48        (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternBegin):
     49        (JSC::Yarr::ByteCompiler::atomParentheticalAssertionBegin):
     50        (JSC::Yarr::ByteCompiler::atomParentheticalAssertionEnd):
     51        (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternEnd):
     52        (JSC::Yarr::ByteCompiler::atomParenthesesOnceEnd):
     53        (JSC::Yarr::ByteCompiler::atomParenthesesTerminalEnd):
     54        (JSC::Yarr::ByteCompiler::emitDisjunction):
     55        * yarr/RegexInterpreter.h:
     56        (JSC::Yarr::ByteTerm::ByteTerm):
     57        (JSC::Yarr::ByteTerm::BackReference):
     58        (JSC::Yarr::ByteTerm::invert):
     59        (JSC::Yarr::ByteTerm::capture):
     60        * yarr/RegexJIT.cpp:
     61        (JSC::Yarr::RegexGenerator::IndirectJumpEntry::IndirectJumpEntry):
     62        (JSC::Yarr::RegexGenerator::IndirectJumpEntry::addJump):
     63        (JSC::Yarr::RegexGenerator::GenerationState::GenerationState):
     64        (JSC::Yarr::RegexGenerator::GenerationState::addIndirectJumpEntry):
     65        (JSC::Yarr::RegexGenerator::GenerationState::emitIndirectJumpTable):
     66        (JSC::Yarr::RegexGenerator::GenerationState::addParenthesesTail):
     67        (JSC::Yarr::RegexGenerator::GenerationState::emitParenthesesTail):
     68        (JSC::Yarr::RegexGenerator::GenerationState::addJumpToNextInteration):
     69        (JSC::Yarr::RegexGenerator::GenerationState::addJumpsToNextInteration):
     70        (JSC::Yarr::RegexGenerator::GenerationState::addDataLabelToNextIteration):
     71        (JSC::Yarr::RegexGenerator::GenerationState::linkToNextIteration):
     72        (JSC::Yarr::RegexGenerator::BacktrackDestination::BacktrackDestination):
     73        (JSC::Yarr::RegexGenerator::BacktrackDestination::clear):
     74        (JSC::Yarr::RegexGenerator::BacktrackDestination::clearDataLabel):
     75        (JSC::Yarr::RegexGenerator::BacktrackDestination::haveDestination):
     76        (JSC::Yarr::RegexGenerator::BacktrackDestination::isStackOffset):
     77        (JSC::Yarr::RegexGenerator::BacktrackDestination::isLabel):
     78        (JSC::Yarr::RegexGenerator::BacktrackDestination::isJumpList):
     79        (JSC::Yarr::RegexGenerator::BacktrackDestination::haveDataLabel):
     80        (JSC::Yarr::RegexGenerator::BacktrackDestination::copyTarget):
     81        (JSC::Yarr::RegexGenerator::BacktrackDestination::copyTo):
     82        (JSC::Yarr::RegexGenerator::BacktrackDestination::addBacktrackJump):
     83        (JSC::Yarr::RegexGenerator::BacktrackDestination::setStackOffset):
     84        (JSC::Yarr::RegexGenerator::BacktrackDestination::setLabel):
     85        (JSC::Yarr::RegexGenerator::BacktrackDestination::setNextBacktrackLabel):
     86        (JSC::Yarr::RegexGenerator::BacktrackDestination::setBacktrackToLabel):
     87        (JSC::Yarr::RegexGenerator::BacktrackDestination::setBacktrackJumpList):
     88        (JSC::Yarr::RegexGenerator::BacktrackDestination::setBacktrackSourceLabel):
     89        (JSC::Yarr::RegexGenerator::BacktrackDestination::setDataLabel):
     90        (JSC::Yarr::RegexGenerator::BacktrackDestination::setSubDataLabelPtr):
     91        (JSC::Yarr::RegexGenerator::BacktrackDestination::linkToNextBacktrack):
     92        (JSC::Yarr::RegexGenerator::BacktrackDestination::getStackOffset):
     93        (JSC::Yarr::RegexGenerator::BacktrackDestination::getLabel):
     94        (JSC::Yarr::RegexGenerator::BacktrackDestination::getBacktrackJumps):
     95        (JSC::Yarr::RegexGenerator::BacktrackDestination::getDataLabel):
     96        (JSC::Yarr::RegexGenerator::BacktrackDestination::jumpToBacktrack):
     97        (JSC::Yarr::RegexGenerator::BacktrackDestination::linkDataLabelToHereIfExists):
     98        (JSC::Yarr::RegexGenerator::BacktrackDestination::plantJumpToBacktrackIfExists):
     99        (JSC::Yarr::RegexGenerator::BacktrackDestination::linkAlternativeBacktracks):
     100        (JSC::Yarr::RegexGenerator::BacktrackDestination::linkAlternativeBacktracksTo):
     101        (JSC::Yarr::RegexGenerator::TermGenerationState::TermGenerationState):
     102        (JSC::Yarr::RegexGenerator::TermGenerationState::resetAlternative):
     103        (JSC::Yarr::RegexGenerator::TermGenerationState::isLastAlternative):
     104        (JSC::Yarr::RegexGenerator::TermGenerationState::clearBacktrack):
     105        (JSC::Yarr::RegexGenerator::TermGenerationState::jumpToBacktrack):
     106        (JSC::Yarr::RegexGenerator::TermGenerationState::plantJumpToBacktrackIfExists):
     107        (JSC::Yarr::RegexGenerator::TermGenerationState::linkDataLabelToBacktrackIfExists):
     108        (JSC::Yarr::RegexGenerator::TermGenerationState::addBacktrackJump):
     109        (JSC::Yarr::RegexGenerator::TermGenerationState::setDataLabelPtr):
     110        (JSC::Yarr::RegexGenerator::TermGenerationState::setBackTrackStackOffset):
     111        (JSC::Yarr::RegexGenerator::TermGenerationState::setBacktrackLabel):
     112        (JSC::Yarr::RegexGenerator::TermGenerationState::linkAlternativeBacktracks):
     113        (JSC::Yarr::RegexGenerator::TermGenerationState::linkAlternativeBacktracksTo):
     114        (JSC::Yarr::RegexGenerator::TermGenerationState::setBacktrackLink):
     115        (JSC::Yarr::RegexGenerator::TermGenerationState::chainBacktracks):
     116        (JSC::Yarr::RegexGenerator::TermGenerationState::chainBacktrackJumps):
     117        (JSC::Yarr::RegexGenerator::TermGenerationState::getBacktrackDestination):
     118        (JSC::Yarr::RegexGenerator::TermGenerationState::propagateBacktrackingFrom):
     119        (JSC::Yarr::RegexGenerator::ParenthesesTail::ParenthesesTail):
     120        (JSC::Yarr::RegexGenerator::ParenthesesTail::processBacktracks):
     121        (JSC::Yarr::RegexGenerator::ParenthesesTail::setNextIteration):
     122        (JSC::Yarr::RegexGenerator::ParenthesesTail::generateCode):
     123        (JSC::Yarr::RegexGenerator::generateAssertionBOL):
     124        (JSC::Yarr::RegexGenerator::generateAssertionEOL):
     125        (JSC::Yarr::RegexGenerator::generateAssertionWordBoundary):
     126        (JSC::Yarr::RegexGenerator::generatePatternCharacterSingle):
     127        (JSC::Yarr::RegexGenerator::generatePatternCharacterPair):
     128        (JSC::Yarr::RegexGenerator::generatePatternCharacterFixed):
     129        (JSC::Yarr::RegexGenerator::generatePatternCharacterGreedy):
     130        (JSC::Yarr::RegexGenerator::generatePatternCharacterNonGreedy):
     131        (JSC::Yarr::RegexGenerator::generateCharacterClassSingle):
     132        (JSC::Yarr::RegexGenerator::generateCharacterClassFixed):
     133        (JSC::Yarr::RegexGenerator::generateCharacterClassGreedy):
     134        (JSC::Yarr::RegexGenerator::generateCharacterClassNonGreedy):
     135        (JSC::Yarr::RegexGenerator::generateParenthesesDisjunction):
     136        (JSC::Yarr::RegexGenerator::generateParenthesesSingle):
     137        (JSC::Yarr::RegexGenerator::generateParenthesesGreedyNoBacktrack):
     138        (JSC::Yarr::RegexGenerator::generateParentheticalAssertion):
     139        (JSC::Yarr::RegexGenerator::generateDisjunction):
     140        (JSC::Yarr::RegexGenerator::compile):
     141        * yarr/RegexPattern.h:
     142        (JSC::Yarr::PatternTerm::PatternTerm):
     143        (JSC::Yarr::PatternTerm::invert):
     144        (JSC::Yarr::PatternTerm::capture):
     145
    11462010-12-03  Chris Rogers  <crogers@google.com>
    2147
  • trunk/JavaScriptCore/assembler/ARMAssembler.h

    r72663 r73307  
    241241
    242242            bool isUsed() const { return m_used; }
     243            bool isSet() const { return (m_offset != -1); }
    243244            void used() { m_used = true; }
    244245        private:
  • trunk/JavaScriptCore/assembler/ARMv7Assembler.h

    r72481 r73307  
    554554
    555555        bool isUsed() const { return m_used; }
     556        bool isSet() const { return (m_offset != -1); }
    556557        void used() { m_used = true; }
    557558    private:
  • trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r71691 r73307  
    242242       
    243243        bool isUsed() const { return m_label.isUsed(); }
     244        bool isSet() const { return m_label.isSet(); }
    244245        void used() { m_label.used(); }
    245246    private:
     
    264265        {
    265266        }
     267       
     268        bool isSet() const { return m_label.isSet(); }
    266269       
    267270    private:
     
    411414        }
    412415       
     416        void clear()
     417        {
     418            m_jumps.clear();
     419        }
     420       
    413421        const JumpVector& jumps() { return m_jumps; }
    414422
  • trunk/JavaScriptCore/assembler/MIPSAssembler.h

    r66846 r73307  
    194194
    195195        bool isUsed() const { return m_used; }
     196        bool isSet() const { return (m_offset != -1); }
    196197        void used() { m_used = true; }
    197198    private:
  • trunk/JavaScriptCore/assembler/X86Assembler.h

    r66150 r73307  
    249249
    250250        bool isUsed() const { return m_used; }
     251        bool isSet() const { return (m_offset != -1); }
    251252        void used() { m_used = true; }
    252253    private:
  • trunk/JavaScriptCore/yarr/RegexCompiler.cpp

    r73065 r73307  
    460460        PatternDisjunction* parenthesesDisjunction = new PatternDisjunction(m_alternative);
    461461        m_pattern.m_disjunctions.append(parenthesesDisjunction);
    462         m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture));
     462        m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture, false));
    463463        m_alternative = parenthesesDisjunction->addNewAlternative();
    464464    }
     
    468468        PatternDisjunction* parenthesesDisjunction = new PatternDisjunction(m_alternative);
    469469        m_pattern.m_disjunctions.append(parenthesesDisjunction);
    470         m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, invert));
     470        m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, false, invert));
    471471        m_alternative = parenthesesDisjunction->addNewAlternative();
    472472        m_invertParentheticalAssertion = invert;
     
    521521            ASSERT((term.type == PatternTerm::TypeParenthesesSubpattern) || (term.type == PatternTerm::TypeParentheticalAssertion));
    522522
    523             if ((term.type == PatternTerm::TypeParenthesesSubpattern) && term.invertOrCapture && (subpatternId == term.parentheses.subpatternId)) {
     523            if ((term.type == PatternTerm::TypeParenthesesSubpattern) && term.capture() && (subpatternId == term.parentheses.subpatternId)) {
    524524                m_alternative->m_terms.append(PatternTerm::ForwardReference());
    525525                return;
     
    846846
    847847            case PatternTerm::TypeParentheticalAssertion:
    848                 if (term.invertOrCapture)
     848                if (term.invert())
    849849                    return false;
    850850
  • trunk/JavaScriptCore/yarr/RegexInterpreter.cpp

    r73124 r73307  
    15231523        int beginTerm = m_bodyDisjunction->terms.size();
    15241524
    1525         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, inputPosition));
     1525        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, false, inputPosition));
    15261526        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
    15271527        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
     
    15361536        int beginTerm = m_bodyDisjunction->terms.size();
    15371537
    1538         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternTerminalBegin, subpatternId, capture, inputPosition));
     1538        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternTerminalBegin, subpatternId, capture, false, inputPosition));
    15391539        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
    15401540        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
     
    15531553        int beginTerm = m_bodyDisjunction->terms.size();
    15541554
    1555         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, inputPosition));
     1555        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, false, inputPosition));
    15561556        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
    15571557        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
     
    15661566        int beginTerm = m_bodyDisjunction->terms.size();
    15671567
    1568         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionBegin, subpatternId, invert, 0));
     1568        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionBegin, subpatternId, false, invert, 0));
    15691569        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
    15701570        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
     
    15831583        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParentheticalAssertionBegin);
    15841584
    1585         bool invertOrCapture = m_bodyDisjunction->terms[beginTerm].invertOrCapture;
     1585        bool invert = m_bodyDisjunction->terms[beginTerm].invert();
    15861586        unsigned subpatternId = m_bodyDisjunction->terms[beginTerm].atom.subpatternId;
    15871587
    1588         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionEnd, subpatternId, invertOrCapture, inputPosition));
     1588        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionEnd, subpatternId, false, invert, inputPosition));
    15891589        m_bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
    15901590        m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
     
    16781678        ByteTerm& parenthesesBegin = m_bodyDisjunction->terms[beginTerm];
    16791679
    1680         bool invertOrCapture = parenthesesBegin.invertOrCapture;
     1680        bool capture = parenthesesBegin.capture();
    16811681        unsigned subpatternId = parenthesesBegin.atom.subpatternId;
    16821682
     
    16921692
    16931693        m_allParenthesesInfo.append(parenthesesDisjunction);
    1694         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, invertOrCapture, inputPosition));
     1694        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture, inputPosition));
    16951695
    16961696        m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
     
    17071707        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
    17081708
    1709         bool invertOrCapture = m_bodyDisjunction->terms[beginTerm].invertOrCapture;
     1709        bool capture = m_bodyDisjunction->terms[beginTerm].capture();
    17101710        unsigned subpatternId = m_bodyDisjunction->terms[beginTerm].atom.subpatternId;
    17111711
    1712         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceEnd, subpatternId, invertOrCapture, inputPosition));
     1712        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceEnd, subpatternId, capture, false, inputPosition));
    17131713        m_bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
    17141714        m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
     
    17291729        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParenthesesSubpatternTerminalBegin);
    17301730
    1731         bool invertOrCapture = m_bodyDisjunction->terms[beginTerm].invertOrCapture;
     1731        bool capture = m_bodyDisjunction->terms[beginTerm].capture();
    17321732        unsigned subpatternId = m_bodyDisjunction->terms[beginTerm].atom.subpatternId;
    17331733
    1734         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternTerminalEnd, subpatternId, invertOrCapture, inputPosition));
     1734        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternTerminalEnd, subpatternId, capture, false, inputPosition));
    17351735        m_bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
    17361736        m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
     
    18151815
    18161816                case PatternTerm::TypeAssertionWordBoundary:
    1817                     assertionWordBoundary(term.invertOrCapture, term.inputPosition - currentCountAlreadyChecked);
     1817                    assertionWordBoundary(term.invert(), term.inputPosition - currentCountAlreadyChecked);
    18181818                    break;
    18191819
     
    18231823
    18241824                case PatternTerm::TypeCharacterClass:
    1825                     atomCharacterClass(term.characterClass, term.invertOrCapture, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
     1825                    atomCharacterClass(term.characterClass, term.invert(), term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
    18261826                    break;
    18271827
     
    18431843                            alternativeFrameLocation += RegexStackSpaceForBackTrackInfoParenthesesOnce;
    18441844                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
    1845                         atomParenthesesOnceBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, alternativeFrameLocation);
     1845                        atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, alternativeFrameLocation);
    18461846                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount);
    18471847                        atomParenthesesOnceEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType);
    18481848                    } else if (term.parentheses.isTerminal) {
    18491849                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
    1850                         atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation + RegexStackSpaceForBackTrackInfoParenthesesOnce);
     1850                        atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation + RegexStackSpaceForBackTrackInfoParenthesesOnce);
    18511851                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount);
    18521852                        atomParenthesesTerminalEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType);
    18531853                    } else {
    18541854                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
    1855                         atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, 0);
     1855                        atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, 0);
    18561856                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
    18571857                        atomParenthesesSubpatternEnd(term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
     
    18661866                    int positiveInputOffset = currentCountAlreadyChecked - term.inputPosition;
    18671867
    1868                     atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invertOrCapture, term.frameLocation, alternativeFrameLocation);
     1868                    atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invert(), term.frameLocation, alternativeFrameLocation);
    18691869                    emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, positiveInputOffset, true);
    18701870                    atomParentheticalAssertionEnd(0, term.frameLocation, term.quantityCount, term.quantityType);
  • trunk/JavaScriptCore/yarr/RegexInterpreter.h

    r73124 r73307  
    8888        TypeCheckInput,
    8989    } type;
    90     bool invertOrCapture;
    9190    union {
    9291        struct {
     
    115114    };
    116115    unsigned frameLocation;
     116    bool m_capture : 1;
     117    bool m_invert : 1;
    117118    int inputPosition;
    118119
    119120    ByteTerm(UChar ch, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
    120121        : frameLocation(frameLocation)
     122        , m_capture(false)
     123        , m_invert(false)
    121124    {
    122125        switch (quantityType) {
     
    140143    ByteTerm(UChar lo, UChar hi, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
    141144        : frameLocation(frameLocation)
     145        , m_capture(false)
     146        , m_invert(false)
    142147    {
    143148        switch (quantityType) {
     
    162167    ByteTerm(CharacterClass* characterClass, bool invert, int inputPos)
    163168        : type(ByteTerm::TypeCharacterClass)
    164         , invertOrCapture(invert)
     169        , m_capture(false)
     170        , m_invert(invert)
    165171    {
    166172        atom.characterClass = characterClass;
     
    170176    }
    171177
    172     ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool invertOrCapture, int inputPos)
     178    ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool capture, int inputPos)
    173179        : type(type)
    174         , invertOrCapture(invertOrCapture)
     180        , m_capture(capture)
     181        , m_invert(false)
    175182    {
    176183        atom.subpatternId = subpatternId;
     
    183190    ByteTerm(Type type, bool invert = false)
    184191        : type(type)
    185         , invertOrCapture(invert)
     192        , m_capture(false)
     193        , m_invert(invert)
    186194    {
    187195        atom.quantityType = QuantifierFixedCount;
     
    189197    }
    190198
    191     ByteTerm(Type type, unsigned subpatternId, bool invertOrCapture, int inputPos)
     199    ByteTerm(Type type, unsigned subpatternId, bool capture, bool invert, int inputPos)
    192200        : type(type)
    193         , invertOrCapture(invertOrCapture)
     201        , m_capture(capture)
     202        , m_invert(invert)
    194203    {
    195204        atom.subpatternId = subpatternId;
     
    229238    static ByteTerm BackReference(unsigned subpatternId, int inputPos)
    230239    {
    231         return ByteTerm(TypeBackReference, subpatternId, false, inputPos);
     240        return ByteTerm(TypeBackReference, subpatternId, false, false, inputPos);
    232241    }
    233242
     
    298307    bool invert()
    299308    {
    300         return invertOrCapture;
     309        return m_invert;
    301310    }
    302311
    303312    bool capture()
    304313    {
    305         return invertOrCapture;
     314        return m_capture;
    306315    }
    307316};
  • trunk/JavaScriptCore/yarr/RegexJIT.cpp

    r73124 r73307  
    288288    }
    289289
     290    struct IndirectJumpEntry {
     291        IndirectJumpEntry(int32_t stackOffset)
     292            : m_stackOffset(stackOffset)
     293        {
     294        }
     295
     296        IndirectJumpEntry(int32_t stackOffset, Jump jump)
     297            : m_stackOffset(stackOffset)
     298        {
     299            addJump(jump);
     300        }
     301       
     302        void addJump(Jump jump)
     303        {
     304            m_relJumps.append(jump);
     305        }
     306       
     307        int32_t m_stackOffset;
     308        JumpList m_relJumps;
     309    };
     310       
    290311    struct AlternativeBacktrackRecord {
    291312        DataLabelPtr dataLabel;
     
    299320    };
    300321
     322    struct ParenthesesTail;
     323    struct TermGenerationState;
     324   
     325    struct GenerationState {
     326        typedef HashMap<int, IndirectJumpEntry*, WTF::IntHash<uint32_t>, UnsignedWithZeroKeyHashTraits<uint32_t> > IndirectJumpHashMap;
     327       
     328        GenerationState()
     329        {
     330        }
     331       
     332        void addIndirectJumpEntry(int32_t stackOffset, Jump jump)
     333        {
     334            IndirectJumpHashMap::iterator result = m_indirectJumpMap.find(stackOffset);
     335           
     336            ASSERT(stackOffset >= 0);
     337           
     338            uint32_t offset = static_cast<uint32_t>(stackOffset);
     339           
     340            if (result == m_indirectJumpMap.end())
     341                m_indirectJumpMap.add(offset, new IndirectJumpEntry(stackOffset, jump));
     342            else
     343                result->second->addJump(jump);
     344        }
     345       
     346        void addIndirectJumpEntry(int32_t stackOffset, JumpList jumps)
     347        {
     348            JumpList::JumpVector jumpVector = jumps.jumps();
     349            size_t size = jumpVector.size();
     350            for (size_t i = 0; i < size; ++i)
     351                addIndirectJumpEntry(stackOffset, jumpVector[i]);
     352           
     353            jumps.empty();
     354        }
     355       
     356        void emitIndirectJumpTable(MacroAssembler* masm)
     357        {
     358            for (IndirectJumpHashMap::iterator iter = m_indirectJumpMap.begin(); iter != m_indirectJumpMap.end(); ++iter) {
     359                IndirectJumpEntry* indJumpEntry = iter->second;
     360                indJumpEntry->m_relJumps.link(masm);
     361                masm->jump(Address(stackPointerRegister, indJumpEntry->m_stackOffset));
     362                delete indJumpEntry;
     363            }
     364        }
     365       
     366        ParenthesesTail* addParenthesesTail(PatternTerm& term)
     367        {
     368            ParenthesesTail* parenthesesTail = new ParenthesesTail(term);
     369            m_parenTails.append(parenthesesTail);
     370            m_parenTailsForIteration.append(parenthesesTail);
     371           
     372            return parenthesesTail;
     373        }
     374       
     375        void emitParenthesesTail(RegexGenerator* generator)
     376        {
     377            unsigned vectorSize = m_parenTails.size();
     378           
     379            // Emit in reverse order so parentTail N can fall through to N-1
     380            for (unsigned index = vectorSize; index > 0; --index) {
     381                JumpList jumpsToNext;
     382                m_parenTails[index-1].get()->generateCode(generator, jumpsToNext, index > 1);
     383                if (index > 1)
     384                    jumpsToNext.linkTo(generator->label(), generator);
     385                else
     386                    addJumpsToNextInteration(jumpsToNext);
     387            }
     388            m_parenTails.clear();
     389        }       
     390       
     391        void addJumpToNextInteration(Jump jump)
     392        {
     393            m_jumpsToNextInteration.append(jump);
     394        }
     395       
     396        void addJumpsToNextInteration(JumpList jumps)
     397        {
     398            m_jumpsToNextInteration.append(jumps);
     399        }
     400       
     401        void addDataLabelToNextIteration(DataLabelPtr dataLabel)
     402        {
     403            m_dataPtrsToNextIteration.append(dataLabel);
     404        }
     405       
     406        void linkToNextIteration(Label label)
     407        {
     408            m_nextIteration = label;
     409           
     410            for (unsigned i = 0; i < m_dataPtrsToNextIteration.size(); ++i)
     411                m_backtrackRecords.append(AlternativeBacktrackRecord(m_dataPtrsToNextIteration[i], m_nextIteration));
     412           
     413            m_dataPtrsToNextIteration.clear();
     414
     415            for (unsigned i = 0; i < m_parenTailsForIteration.size(); ++i)
     416                m_parenTailsForIteration[i]->setNextIteration(m_nextIteration);
     417           
     418            m_parenTailsForIteration.clear();           
     419        }
     420
     421        void linkToNextIteration(RegexGenerator* generator)
     422        {
     423            m_jumpsToNextInteration.linkTo(m_nextIteration, generator);
     424        }       
     425       
     426        Vector<AlternativeBacktrackRecord> m_backtrackRecords;
     427        IndirectJumpHashMap m_indirectJumpMap;
     428        Label m_nextIteration;
     429        Vector<OwnPtr<ParenthesesTail> > m_parenTails;
     430        JumpList m_jumpsToNextInteration;
     431        Vector<DataLabelPtr> m_dataPtrsToNextIteration;
     432        Vector<ParenthesesTail*> m_parenTailsForIteration;
     433    };
     434
     435    struct BacktrackDestination {
     436        typedef enum {
     437            NoBacktrack,
     438            BacktrackLabel,
     439            BacktrackStackOffset,
     440            BacktrackJumpList,
     441            BacktrackLinked
     442        } BacktrackType;
     443       
     444        BacktrackDestination()
     445            : m_backtrackType(NoBacktrack)
     446            , m_backtrackToLabel(0)
     447            , m_subDataLabelPtr(0)
     448            , m_nextBacktrack(0)
     449            , m_backtrackSourceLabel(0)
     450            , m_backtrackSourceJumps(0)
     451        {
     452        }
     453       
     454        BacktrackDestination(int32_t stackOffset)
     455            : m_backtrackType(BacktrackStackOffset)
     456            , m_backtrackStackOffset(stackOffset)
     457            , m_backtrackToLabel(0)
     458            , m_subDataLabelPtr(0)
     459            , m_nextBacktrack(0)
     460            , m_backtrackSourceLabel(0)
     461            , m_backtrackSourceJumps(0)
     462        {
     463        }
     464       
     465        BacktrackDestination(Label label)
     466            : m_backtrackType(BacktrackLabel)
     467            , m_backtrackLabel(label)
     468            , m_backtrackToLabel(0)
     469            , m_subDataLabelPtr(0)
     470            , m_nextBacktrack(0)
     471            , m_backtrackSourceLabel(0)
     472            , m_backtrackSourceJumps(0)
     473        {
     474        }
     475       
     476        void clear()
     477        {
     478            m_backtrackType = NoBacktrack;
     479            clearDataLabel();
     480            m_nextBacktrack = 0;
     481        }
     482       
     483        void clearDataLabel()
     484        {
     485            m_dataLabelPtr = DataLabelPtr();
     486        }
     487       
     488        bool hasDestination()
     489        {
     490            return (m_backtrackType != NoBacktrack);
     491        }
     492       
     493        bool isStackOffset()
     494        {
     495            return (m_backtrackType == BacktrackStackOffset);
     496        }
     497       
     498        bool isLabel()
     499        {
     500            return (m_backtrackType == BacktrackLabel);
     501        }
     502       
     503        bool isJumpList()
     504        {
     505            return (m_backtrackType == BacktrackJumpList);
     506        }
     507       
     508        bool hasDataLabel()
     509        {
     510            return m_dataLabelPtr.isSet();
     511        }
     512       
     513        void copyTarget(BacktrackDestination& rhs, bool copyDataLabel = true)
     514        {
     515            m_backtrackType = rhs.m_backtrackType;
     516            if (m_backtrackType == BacktrackStackOffset)
     517                m_backtrackStackOffset = rhs.m_backtrackStackOffset;
     518            else if (m_backtrackType == BacktrackLabel)
     519                m_backtrackLabel = rhs.m_backtrackLabel;
     520            if (copyDataLabel)
     521                m_dataLabelPtr = rhs.m_dataLabelPtr;
     522            m_backtrackSourceJumps = rhs.m_backtrackSourceJumps;
     523            m_backtrackSourceLabel = rhs.m_backtrackSourceLabel;
     524        }
     525       
     526        void copyTo(BacktrackDestination& lhs)
     527        {
     528            lhs.m_backtrackType = m_backtrackType;
     529            if (m_backtrackType == BacktrackStackOffset)
     530                lhs.m_backtrackStackOffset = m_backtrackStackOffset;
     531            else if (m_backtrackType == BacktrackLabel)
     532                lhs.m_backtrackLabel = m_backtrackLabel;
     533            lhs.m_backtrackSourceJumps = m_backtrackSourceJumps;
     534            lhs.m_backtrackSourceLabel = m_backtrackSourceLabel;
     535            lhs.m_dataLabelPtr = m_dataLabelPtr;
     536            lhs.m_backTrackJumps = m_backTrackJumps;
     537        }
     538       
     539        void addBacktrackJump(Jump jump)
     540        {
     541            m_backTrackJumps.append(jump);
     542        }
     543
     544        void setStackOffset(int32_t stackOffset)
     545        {
     546            m_backtrackType = BacktrackStackOffset;
     547            m_backtrackStackOffset = stackOffset;
     548        }
     549       
     550        void setLabel(Label label)
     551        {
     552            m_backtrackType = BacktrackLabel;
     553            m_backtrackLabel = label;
     554        }
     555       
     556        void setNextBacktrackLabel(Label label)
     557        {
     558            if (m_nextBacktrack)
     559                m_nextBacktrack->setLabel(label);
     560        }
     561       
     562        void setBacktrackToLabel(Label* backtrackToLabel)
     563        {
     564            m_backtrackToLabel = backtrackToLabel;
     565        }
     566       
     567        void setBacktrackJumpList(JumpList* jumpList)
     568        {
     569            m_backtrackType = BacktrackJumpList;
     570            m_backtrackSourceJumps = jumpList;
     571        }
     572       
     573        void setBacktrackSourceLabel(Label* backtrackSourceLabel)
     574        {
     575            m_backtrackSourceLabel = backtrackSourceLabel;
     576        }
     577       
     578        void setDataLabel(DataLabelPtr dp)
     579        {
     580            if (m_subDataLabelPtr) {
     581                *m_subDataLabelPtr = dp;
     582                m_subDataLabelPtr = 0;
     583            } else
     584                m_dataLabelPtr = dp;
     585        }
     586       
     587        void setSubDataLabelPtr(DataLabelPtr* subDataLabelPtr)
     588        {
     589            m_subDataLabelPtr = subDataLabelPtr;
     590        }
     591
     592        void linkToNextBacktrack(BacktrackDestination* nextBacktrack)
     593        {
     594            m_nextBacktrack = nextBacktrack;
     595        }
     596                                 
     597        int32_t getStackOffset()
     598        {
     599            ASSERT(m_backtrackType == BacktrackStackOffset);
     600            return m_backtrackStackOffset;
     601        }
     602       
     603        Label getLabel()
     604        {
     605            ASSERT(m_backtrackType == BacktrackLabel);
     606            return m_backtrackLabel;
     607        }
     608       
     609        JumpList& getBacktrackJumps()
     610        {
     611            return m_backTrackJumps;
     612        }
     613       
     614        DataLabelPtr& getDataLabel()
     615        {
     616            return m_dataLabelPtr;
     617        }
     618       
     619        void jumpToBacktrack(MacroAssembler* masm)
     620        {
     621            if (isJumpList()) {
     622                if (m_backtrackSourceLabel && (m_backtrackSourceLabel->isSet()))
     623                    masm->jump().linkTo(*m_backtrackSourceLabel, masm);
     624                else
     625                    m_backtrackSourceJumps->append(masm->jump());
     626            } else if (isStackOffset())
     627                masm->jump(Address(stackPointerRegister, m_backtrackStackOffset));
     628            else if (isLabel())
     629                masm->jump().linkTo(m_backtrackLabel, masm);
     630            else
     631                m_backTrackJumps.append(masm->jump());
     632        }
     633       
     634        void jumpToBacktrack(RegexGenerator* generator, Jump jump)
     635        {
     636            if (isJumpList()) {
     637                if (m_backtrackSourceLabel && (m_backtrackSourceLabel->isSet()))
     638                    jump.linkTo(*m_backtrackSourceLabel, generator);
     639                else
     640                    m_backtrackSourceJumps->append(jump);
     641            } else if (isStackOffset())
     642                generator->m_expressionState.addIndirectJumpEntry(getStackOffset(), jump);
     643            else if (isLabel())
     644                jump.linkTo(getLabel(), generator);
     645            else
     646                m_backTrackJumps.append(jump);
     647        }
     648       
     649        void jumpToBacktrack(RegexGenerator* generator, JumpList& jumps)
     650        {
     651            if (isJumpList()) {
     652                if (m_backtrackSourceLabel && (m_backtrackSourceLabel->isSet()))
     653                    jumps.linkTo(*m_backtrackSourceLabel, generator);
     654                else
     655                    m_backtrackSourceJumps->append(jumps);
     656            } else if (isStackOffset())
     657                generator->m_expressionState.addIndirectJumpEntry(getStackOffset(), jumps);
     658            else if (isLabel())
     659                jumps.linkTo(getLabel(), generator);
     660            else
     661                m_backTrackJumps.append(jumps);
     662        }
     663
     664        bool linkDataLabelToHereIfExists(RegexGenerator* generator)
     665        {
     666            if (hasDataLabel()) {
     667                generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(getDataLabel(), generator->label()));
     668                clearDataLabel();
     669                return true;
     670            }
     671           
     672            return false;
     673        }       
     674               
     675        bool plantJumpToBacktrackIfExists(RegexGenerator* generator)
     676        {
     677            if (isJumpList()) {
     678                if (m_backtrackSourceLabel && (m_backtrackSourceLabel->isSet()))
     679                    generator->jump(*m_backtrackSourceLabel);
     680                else
     681                    m_backtrackSourceJumps->append(generator->jump());
     682
     683                return true;
     684            }
     685
     686            if (isStackOffset()) {
     687                generator->jump(Address(stackPointerRegister, getStackOffset()));
     688                return true;
     689            }
     690           
     691            if (isLabel()) {
     692                generator->jump(getLabel());
     693                if (hasDataLabel()) {
     694                    generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(getDataLabel(), getLabel()));
     695                    clearDataLabel();
     696                }               
     697                return true;
     698            }
     699           
     700            return false;
     701        }
     702
     703        void linkAlternativeBacktracks(RegexGenerator* generator, bool nextIteration = false)
     704        {
     705            Label hereLabel = generator->label();
     706           
     707            if (m_backtrackToLabel) {
     708                *m_backtrackToLabel = hereLabel;
     709                m_backtrackToLabel = 0;
     710            }
     711           
     712            m_backTrackJumps.link(generator);
     713           
     714            if (nextIteration)
     715                generator->m_expressionState.linkToNextIteration(hereLabel);
     716           
     717            if (hasDataLabel()) {
     718                generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(getDataLabel(), hereLabel));
     719                // data label cleared as a result of the clear() below
     720            }
     721           
     722            clear();
     723        }
     724       
     725        void linkAlternativeBacktracksTo(RegexGenerator* generator, Label label, bool nextIteration = false)
     726        {
     727            m_backTrackJumps.linkTo(label, generator);
     728           
     729            if (nextIteration)
     730                generator->m_expressionState.linkToNextIteration(label);
     731           
     732            if (hasDataLabel()) {
     733                generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(getDataLabel(), label));
     734                clearDataLabel();
     735            }
     736        }
     737       
     738    private:
     739        BacktrackType m_backtrackType;
     740        int32_t m_backtrackStackOffset;
     741        Label m_backtrackLabel;
     742        DataLabelPtr m_dataLabelPtr;
     743        Label* m_backtrackToLabel;
     744        DataLabelPtr* m_subDataLabelPtr;
     745        BacktrackDestination* m_nextBacktrack;
     746        Label* m_backtrackSourceLabel;
     747        JumpList* m_backtrackSourceJumps;
     748        JumpList m_backTrackJumps;
     749    };
     750       
    301751    struct TermGenerationState {
    302752        TermGenerationState(PatternDisjunction* disjunction, unsigned checkedTotal)
    303753            : disjunction(disjunction)
    304754            , checkedTotal(checkedTotal)
     755            , m_linkedBacktrack(0)
    305756        {
    306757        }
     
    308759        void resetAlternative()
    309760        {
    310             isBackTrackGenerated = false;
     761            m_backtrack.clear();
    311762            alt = 0;
    312763        }
     
    323774            return disjunction->m_alternatives[alt];
    324775        }
    325 
     776        bool isLastAlternative()
     777        {
     778            return (alt + 1) == disjunction->m_alternatives.size();
     779        }
     780       
    326781        void resetTerm()
    327782        {
     
    374829        }
    375830
    376         void jumpToBacktrack(Jump jump, MacroAssembler* masm)
    377         {
    378             if (isBackTrackGenerated)
    379                 jump.linkTo(backtrackLabel, masm);
    380             else
    381                 backTrackJumps.append(jump);
    382         }
    383         void jumpToBacktrack(JumpList& jumps, MacroAssembler* masm)
    384         {
    385             if (isBackTrackGenerated)
    386                 jumps.linkTo(backtrackLabel, masm);
    387             else
    388                 backTrackJumps.append(jumps);
    389         }
    390         bool plantJumpToBacktrackIfExists(MacroAssembler* masm)
    391         {
    392             if (isBackTrackGenerated) {
    393                 masm->jump(backtrackLabel);
     831        void clearBacktrack()
     832        {
     833            m_backtrack.clear();
     834            m_linkedBacktrack = 0;
     835        }
     836       
     837        void jumpToBacktrack(MacroAssembler* masm)
     838        {
     839            m_backtrack.jumpToBacktrack(masm);
     840        }
     841       
     842        void jumpToBacktrack(RegexGenerator* generator, Jump jump)
     843        {
     844            m_backtrack.jumpToBacktrack(generator, jump);
     845        }
     846
     847        void jumpToBacktrack(RegexGenerator* generator, JumpList& jumps)
     848        {
     849            m_backtrack.jumpToBacktrack(generator, jumps);
     850        }
     851       
     852        bool plantJumpToBacktrackIfExists(RegexGenerator* generator)
     853        {
     854            return m_backtrack.plantJumpToBacktrackIfExists(generator);
     855        }
     856       
     857        bool linkDataLabelToBacktrackIfExists(RegexGenerator* generator)
     858        {
     859            if ((m_backtrack.isLabel()) && (m_backtrack.hasDataLabel())) {
     860                generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(m_backtrack.getDataLabel(), m_backtrack.getLabel()));
     861                m_backtrack.clearDataLabel();
    394862                return true;
    395863            }
     864           
    396865            return false;
    397         }
     866        }       
     867
    398868        void addBacktrackJump(Jump jump)
    399869        {
    400             backTrackJumps.append(jump);
    401         }
    402         void setBacktrackGenerated(Label label)
    403         {
    404             isBackTrackGenerated = true;
    405             backtrackLabel = label;
    406         }
    407         void linkAlternativeBacktracks(MacroAssembler* masm)
    408         {
    409             isBackTrackGenerated = false;
    410             backTrackJumps.link(masm);
    411         }
    412         void linkAlternativeBacktracksTo(Label label, MacroAssembler* masm)
    413         {
    414             isBackTrackGenerated = false;
    415             backTrackJumps.linkTo(label, masm);
    416         }
    417         void propagateBacktrackingFrom(TermGenerationState& nestedParenthesesState, MacroAssembler* masm)
    418         {
    419             jumpToBacktrack(nestedParenthesesState.backTrackJumps, masm);
    420             if (nestedParenthesesState.isBackTrackGenerated)
    421                 setBacktrackGenerated(nestedParenthesesState.backtrackLabel);
     870            m_backtrack.addBacktrackJump(jump);
     871        }
     872
     873        void setBacktrackDataLabel(DataLabelPtr dp)
     874        {
     875            m_backtrack.setDataLabel(dp);
     876        }
     877
     878        void setBackTrackStackOffset(int32_t stackOffset)
     879        {
     880            m_backtrack.setStackOffset(stackOffset);
     881        }
     882       
     883        void setBacktrackLabel(Label label)
     884        {
     885            m_backtrack.setLabel(label);
     886        }
     887
     888        void linkAlternativeBacktracks(RegexGenerator* generator, bool nextIteration = false)
     889        {
     890            m_backtrack.linkAlternativeBacktracks(generator, nextIteration);
     891            m_linkedBacktrack = 0;
     892        }
     893
     894        void linkAlternativeBacktracksTo(RegexGenerator* generator, Label label, bool nextIteration = false)
     895        {
     896            m_backtrack.linkAlternativeBacktracksTo(generator, label, nextIteration);
     897        }
     898
     899        void setBacktrackLink(BacktrackDestination* linkedBacktrack)
     900        {
     901            m_linkedBacktrack = linkedBacktrack;
     902        }
     903       
     904        void chainBacktracks(BacktrackDestination* followonBacktrack)
     905        {
     906            if (m_linkedBacktrack)
     907                m_linkedBacktrack->linkToNextBacktrack(followonBacktrack);
     908        }
     909       
     910        void chainBacktrackJumps(JumpList* jumpList)
     911        {
     912            if (m_linkedBacktrack && !(m_linkedBacktrack->hasDestination()))
     913                m_linkedBacktrack->setBacktrackJumpList(jumpList);
     914        }
     915       
     916        BacktrackDestination& getBacktrackDestination()
     917        {
     918            return m_backtrack;
     919        }
     920
     921        void propagateBacktrackingFrom(RegexGenerator* generator, BacktrackDestination& backtrack, bool doJump = true)
     922        {
     923            if (doJump)
     924                m_backtrack.jumpToBacktrack(generator, backtrack.getBacktrackJumps());
     925            if (backtrack.hasDestination()) {
     926                if (m_backtrack.hasDataLabel())
     927                    generator->m_expressionState.addDataLabelToNextIteration(m_backtrack.getDataLabel());
     928               
     929                m_backtrack.copyTarget(backtrack, doJump);
     930            }
    422931        }
    423932
     
    427936        unsigned alt;
    428937        unsigned t;
    429         JumpList backTrackJumps;
    430         Label backtrackLabel;
    431         bool isBackTrackGenerated;
     938        BacktrackDestination m_backtrack;
     939        BacktrackDestination* m_linkedBacktrack;
     940       
    432941    };
    433942
     943    struct ParenthesesTail {
     944        ParenthesesTail(PatternTerm& term)
     945            : m_term(term)
     946        {
     947        }
     948       
     949        void processBacktracks(RegexGenerator* generator, TermGenerationState& state, TermGenerationState& parenthesesState, Label nonGreedyTryParentheses, Label fallThrough)
     950        {
     951            m_nonGreedyTryParentheses = nonGreedyTryParentheses;
     952            m_fallThrough = fallThrough;
     953
     954            parenthesesState.getBacktrackDestination().copyTo(m_parenBacktrack);
     955            state.chainBacktracks(&m_backtrack);
     956            BacktrackDestination& stateBacktrack = state.getBacktrackDestination();
     957            stateBacktrack.copyTo(m_backtrack);
     958            stateBacktrack.setBacktrackToLabel(&m_backtrackToLabel);
     959            state.setBacktrackLink(&m_backtrack);
     960            stateBacktrack.setSubDataLabelPtr(&m_dataAfterLabelPtr);
     961           
     962            m_doDirectBacktrack = m_parenBacktrack.hasDestination();
     963           
     964            if ((m_term.quantityType == QuantifierGreedy) || (m_term.quantityType == QuantifierNonGreedy))
     965                m_doDirectBacktrack = false;
     966
     967            if (m_doDirectBacktrack)
     968                state.propagateBacktrackingFrom(generator, m_parenBacktrack, false);
     969            else {
     970                stateBacktrack.setBacktrackJumpList(&m_pattBacktrackJumps);
     971                stateBacktrack.setBacktrackSourceLabel(&m_backtrackFromAfterParens);
     972            }
     973           
     974            parenthesesState.chainBacktrackJumps(&m_pattBacktrackJumps);
     975        }
     976
     977        void setNextIteration(Label nextIteration)
     978        {
     979            if (!m_backtrackToLabel.isSet())
     980                m_backtrackToLabel = nextIteration;
     981        }
     982
     983        void addAfterParenJump(Jump jump)
     984        {
     985            m_pattBacktrackJumps.append(jump);
     986        }
     987       
     988        void generateCode(RegexGenerator* generator, JumpList& jumpsToNext, bool nextBacktrackFallThrough)
     989        {
     990            const RegisterID indexTemporary = regT0;
     991            unsigned parenthesesFrameLocation = m_term.frameLocation;
     992           
     993            if (!m_backtrack.hasDestination()) {
     994                if (m_backtrackToLabel.isSet()) {
     995                    m_backtrack.setLabel(m_backtrackToLabel);
     996                    nextBacktrackFallThrough = false;
     997                } else
     998                    m_backtrack.setBacktrackJumpList(&jumpsToNext);
     999            } else
     1000                nextBacktrackFallThrough = false;
     1001           
     1002            // A failure AFTER the parens jumps here - Backtrack to this paren
     1003            m_backtrackFromAfterParens = generator->label();
     1004           
     1005            if (m_dataAfterLabelPtr.isSet())
     1006                generator->m_expressionState.m_backtrackRecords.append(AlternativeBacktrackRecord(m_dataAfterLabelPtr, m_backtrackFromAfterParens));
     1007
     1008            m_pattBacktrackJumps.link(generator);
     1009           
     1010            if (m_term.quantityType == QuantifierGreedy) {
     1011                // If this is -1 we have now tested with both with and without the parens.
     1012                generator->loadFromFrame(parenthesesFrameLocation, indexTemporary);
     1013                m_backtrack.jumpToBacktrack(generator, generator->branch32(Equal, indexTemporary, Imm32(-1)));
     1014            } else if (m_term.quantityType == QuantifierNonGreedy) {
     1015                // If this is -1 we have now tested with both with and without the parens.
     1016                generator->loadFromFrame(parenthesesFrameLocation, indexTemporary);
     1017                generator->branch32(Equal, indexTemporary, Imm32(-1)).linkTo(m_nonGreedyTryParentheses, generator);
     1018            }
     1019           
     1020            if (!m_doDirectBacktrack)
     1021                m_parenBacktrack.plantJumpToBacktrackIfExists(generator);
     1022           
     1023            // A failure WITHIN the parens jumps here
     1024            m_parenBacktrack.linkAlternativeBacktracks(generator);
     1025           
     1026            if (m_term.capture())
     1027                generator->store32(Imm32(-1), Address(output, (m_term.parentheses.subpatternId << 1) * sizeof(int)));
     1028           
     1029            if (m_term.quantityType == QuantifierGreedy) {
     1030                generator->storeToFrame(Imm32(-1), parenthesesFrameLocation);
     1031                generator->jump().linkTo(m_fallThrough, generator);
     1032            } else if (!nextBacktrackFallThrough)
     1033                m_backtrack.jumpToBacktrack(generator);
     1034
     1035            if (!m_doDirectBacktrack)
     1036                m_backtrack.setNextBacktrackLabel(m_backtrackFromAfterParens);
     1037        }
     1038       
     1039        PatternTerm& m_term;
     1040        Label m_nonGreedyTryParentheses;
     1041        Label m_fallThrough;
     1042        Label m_backtrackToLabel;
     1043        Label m_backtrackFromAfterParens;
     1044        DataLabelPtr m_dataAfterLabelPtr;
     1045        JumpList m_pattBacktrackJumps;
     1046        BacktrackDestination m_parenBacktrack;
     1047        BacktrackDestination m_backtrack;
     1048        bool m_doDirectBacktrack;
     1049    };
     1050   
     1051   
    4341052    void generateAssertionBOL(TermGenerationState& state)
    4351053    {
     
    4451063            readCharacter(state.inputOffset() - 1, character);
    4461064            matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
    447             state.jumpToBacktrack(jump(), this);
     1065            state.jumpToBacktrack(this);
    4481066
    4491067            matchDest.link(this);
     
    4511069            // Erk, really should poison out these alternatives early. :-/
    4521070            if (term.inputPosition)
    453                 state.jumpToBacktrack(jump(), this);
     1071                state.jumpToBacktrack(this);
    4541072            else
    455                 state.jumpToBacktrack(branch32(NotEqual, index, Imm32(state.checkedTotal)), this);
     1073                state.jumpToBacktrack(this, branch32(NotEqual, index, Imm32(state.checkedTotal)));
    4561074        }
    4571075    }
     
    4701088            readCharacter(state.inputOffset(), character);
    4711089            matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
    472             state.jumpToBacktrack(jump(), this);
     1090            state.jumpToBacktrack(this);
    4731091
    4741092            matchDest.link(this);
    4751093        } else {
    4761094            if (term.inputPosition == state.checkedTotal)
    477                 state.jumpToBacktrack(notAtEndOfInput(), this);
     1095                state.jumpToBacktrack(this, notAtEndOfInput());
    4781096            // Erk, really should poison out these alternatives early. :-/
    4791097            else
    480                 state.jumpToBacktrack(jump(), this);
     1098                state.jumpToBacktrack(this);
    4811099        }
    4821100    }
     
    5121130        JumpList nonWordCharThenWordChar;
    5131131        JumpList nonWordCharThenNonWordChar;
    514         if (term.invertOrCapture) {
     1132        if (term.invert()) {
    5151133            matchAssertionWordchar(state, nonWordCharThenNonWordChar, nonWordCharThenWordChar);
    5161134            nonWordCharThenWordChar.append(jump());
     
    5191137            nonWordCharThenNonWordChar.append(jump());
    5201138        }
    521         state.jumpToBacktrack(nonWordCharThenNonWordChar, this);
     1139        state.jumpToBacktrack(this, nonWordCharThenNonWordChar);
    5221140
    5231141        // We jump here if the last character was a wordchar.
     
    5251143        JumpList wordCharThenWordChar;
    5261144        JumpList wordCharThenNonWordChar;
    527         if (term.invertOrCapture) {
     1145        if (term.invert()) {
    5281146            matchAssertionWordchar(state, wordCharThenNonWordChar, wordCharThenWordChar);
    5291147            wordCharThenWordChar.append(jump());
     
    5331151        }
    5341152
    535         state.jumpToBacktrack(wordCharThenWordChar, this);
     1153        state.jumpToBacktrack(this, wordCharThenWordChar);
    5361154       
    5371155        nonWordCharThenWordChar.link(this);
     
    5471165            readCharacter(state.inputOffset(), character);
    5481166            or32(Imm32(32), character);
    549             state.jumpToBacktrack(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))), this);
     1167            state.jumpToBacktrack(this, branch32(NotEqual, character, Imm32(Unicode::toLower(ch))));
    5501168        } else {
    5511169            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
    552             state.jumpToBacktrack(jumpIfCharNotEquals(ch, state.inputOffset()), this);
     1170            state.jumpToBacktrack(this, jumpIfCharNotEquals(ch, state.inputOffset()));
    5531171        }
    5541172    }
     
    5731191            load32WithUnalignedHalfWords(BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), character);
    5741192            or32(Imm32(mask), character);
    575             state.jumpToBacktrack(branch32(NotEqual, character, Imm32(chPair | mask)), this);
     1193            state.jumpToBacktrack(this, branch32(NotEqual, character, Imm32(chPair | mask)));
    5761194        } else
    577             state.jumpToBacktrack(branch32WithUnalignedHalfWords(NotEqual, BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), Imm32(chPair)), this);
     1195            state.jumpToBacktrack(this, branch32WithUnalignedHalfWords(NotEqual, BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), Imm32(chPair)));
    5781196    }
    5791197
     
    5921210            load16(BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), character);
    5931211            or32(Imm32(32), character);
    594             state.jumpToBacktrack(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))), this);
     1212            state.jumpToBacktrack(this, branch32(NotEqual, character, Imm32(Unicode::toLower(ch))));
    5951213        } else {
    5961214            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
    597             state.jumpToBacktrack(branch16(NotEqual, BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), Imm32(ch)), this);
     1215            state.jumpToBacktrack(this, branch16(NotEqual, BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), Imm32(ch)));
    5981216        }
    5991217        add32(Imm32(1), countRegister);
     
    6321250        Label backtrackBegin(this);
    6331251        loadFromFrame(term.frameLocation, countRegister);
    634         state.jumpToBacktrack(branchTest32(Zero, countRegister), this);
     1252        state.jumpToBacktrack(this, branchTest32(Zero, countRegister));
    6351253        sub32(Imm32(1), countRegister);
    6361254        sub32(Imm32(1), index);
     
    6401258        storeToFrame(countRegister, term.frameLocation);
    6411259
    642         state.setBacktrackGenerated(backtrackBegin);
     1260        state.setBacktrackLabel(backtrackBegin);
    6431261    }
    6441262
     
    6561274        Label hardFail(this);
    6571275        sub32(countRegister, index);
    658         state.jumpToBacktrack(jump(), this);
     1276        state.jumpToBacktrack(this);
    6591277
    6601278        Label backtrackBegin(this);
     
    6791297        storeToFrame(countRegister, term.frameLocation);
    6801298
    681         state.setBacktrackGenerated(backtrackBegin);
     1299        state.setBacktrackLabel(backtrackBegin);
    6821300    }
    6831301
     
    6911309        matchCharacterClass(character, matchDest, term.characterClass);
    6921310
    693         if (term.invertOrCapture)
    694             state.jumpToBacktrack(matchDest, this);
     1311        if (term.invert())
     1312            state.jumpToBacktrack(this, matchDest);
    6951313        else {
    696             state.jumpToBacktrack(jump(), this);
     1314            state.jumpToBacktrack(this);
    6971315            matchDest.link(this);
    6981316        }
     
    7131331        matchCharacterClass(character, matchDest, term.characterClass);
    7141332
    715         if (term.invertOrCapture)
    716             state.jumpToBacktrack(matchDest, this);
     1333        if (term.invert())
     1334            state.jumpToBacktrack(this, matchDest);
    7171335        else {
    718             state.jumpToBacktrack(jump(), this);
     1336            state.jumpToBacktrack(this);
    7191337            matchDest.link(this);
    7201338        }
     
    7361354        failures.append(atEndOfInput());
    7371355
    738         if (term.invertOrCapture) {
     1356        if (term.invert()) {
    7391357            readCharacter(state.inputOffset(), character);
    7401358            matchCharacterClass(character, failures, term.characterClass);
     
    7571375        Label backtrackBegin(this);
    7581376        loadFromFrame(term.frameLocation, countRegister);
    759         state.jumpToBacktrack(branchTest32(Zero, countRegister), this);
     1377        state.jumpToBacktrack(this, branchTest32(Zero, countRegister));
    7601378        sub32(Imm32(1), countRegister);
    7611379        sub32(Imm32(1), index);
     
    7651383        storeToFrame(countRegister, term.frameLocation);
    7661384
    767         state.setBacktrackGenerated(backtrackBegin);
     1385        state.setBacktrackLabel(backtrackBegin);
    7681386    }
    7691387
     
    7801398        Label hardFail(this);
    7811399        sub32(countRegister, index);
    782         state.jumpToBacktrack(jump(), this);
     1400        state.jumpToBacktrack(this);
    7831401
    7841402        Label backtrackBegin(this);
     
    7921410        matchCharacterClass(character, matchDest, term.characterClass);
    7931411
    794         if (term.invertOrCapture)
     1412        if (term.invert())
    7951413            matchDest.linkTo(hardFail, this);
    7961414        else {
     
    8051423        storeToFrame(countRegister, term.frameLocation);
    8061424
    807         state.setBacktrackGenerated(backtrackBegin);
     1425        state.setBacktrackLabel(backtrackBegin);
    8081426    }
    8091427
     
    8371455                skip.link(this);
    8381456
    839                 state.setBacktrackGenerated(backtrackBegin);
    840 
    841                 state.jumpToBacktrack(jumpIfNoAvailableInput(countToCheck), this);
     1457                state.setBacktrackLabel(backtrackBegin);
     1458
     1459                state.jumpToBacktrack(this, jumpIfNoAvailableInput(countToCheck));
    8421460                state.checkedTotal += countToCheck;
    8431461            }
     
    8491467        } else {
    8501468            JumpList successes;
     1469            bool propogateBacktrack = false;
    8511470
    8521471            for (state.resetAlternative(); state.alternativeValid(); state.nextAlternative()) {
     
    8671486                // Matched an alternative.
    8681487                DataLabelPtr dataLabel = storeToFrameWithPatch(alternativeFrameLocation);
    869                 successes.append(jump());
     1488               
     1489                if (!state.isLastAlternative() || countToCheck)
     1490                    successes.append(jump());
    8701491
    8711492                // Alternative did not match.
    872                 Label backtrackLocation(this);
     1493
     1494                state.setBacktrackDataLabel(dataLabel);
    8731495               
    874                 // Can we backtrack the alternative? - if so, do so.  If not, just fall through to the next one.
    875                 state.plantJumpToBacktrackIfExists(this);
    876                
    877                 state.linkAlternativeBacktracks(this);
     1496                // Do we have a backtrack destination?
     1497                //    if so, link the data label to it.
     1498                state.linkDataLabelToBacktrackIfExists(this);
     1499
     1500                if (!state.isLastAlternative() || countToCheck)
     1501                    state.linkAlternativeBacktracks(this);
    8781502
    8791503                if (countToCheck) {
    8801504                    sub32(Imm32(countToCheck), index);
    8811505                    state.checkedTotal -= countToCheck;
    882                 }
    883 
    884                 m_backtrackRecords.append(AlternativeBacktrackRecord(dataLabel, backtrackLocation));
     1506                } else if (state.isLastAlternative())
     1507                    propogateBacktrack = true;
    8851508            }
    8861509            // We fall through to here when the last alternative fails.
    8871510            // Add a backtrack out of here for the parenthese handling code to link up.
    888             state.addBacktrackJump(jump());
    889 
    890             // Generate a trampoline for the parens code to backtrack to, to retry the
     1511            if (!propogateBacktrack)
     1512                state.addBacktrackJump(jump());
     1513
     1514            // Save address on stack for the parens code to backtrack to, to retry the
    8911515            // next alternative.
    892             state.setBacktrackGenerated(label());
    893             loadFromFrameAndJump(alternativeFrameLocation);
    894 
    895             // FIXME: both of the above hooks are a little inefficient, in that you
    896             // may end up trampolining here, just to trampoline back out to the
    897             // parentheses code, or vice versa.  We can probably eliminate a jump
    898             // by restructuring, but coding this way for now for simplicity during
    899             // development.
     1516            state.setBackTrackStackOffset(alternativeFrameLocation * sizeof(void*));
    9001517
    9011518            successes.link(this);
     
    9181535
    9191536        // optimized case - no capture & no quantifier can be handled in a light-weight manner.
    920         if (!term.invertOrCapture && (term.quantityType == QuantifierFixedCount)) {
     1537        if (!term.capture() && (term.quantityType == QuantifierFixedCount)) {
    9211538            TermGenerationState parenthesesState(disjunction, state.checkedTotal);
    9221539            generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
    9231540            // this expects that any backtracks back out of the parentheses will be in the
    924             // parenthesesState's backTrackJumps vector, and that if they need backtracking
    925             // they will have set an entry point on the parenthesesState's backtrackLabel.
    926             state.propagateBacktrackingFrom(parenthesesState, this);
     1541            // parenthesesState's m_backTrackJumps vector, and that if they need backtracking
     1542            // they will have set an entry point on the parenthesesState's m_backtrackLabel.
     1543            state.propagateBacktrackingFrom(this, parenthesesState.getBacktrackDestination());
    9271544        } else {
    9281545            Jump nonGreedySkipParentheses;
     
    9381555
    9391556            // store the match start index
    940             if (term.invertOrCapture) {
     1557            if (term.capture()) {
    9411558                int inputOffset = state.inputOffset() - preCheckedCount;
    9421559                if (inputOffset) {
     
    9481565            }
    9491566
     1567            ParenthesesTail* parenthesesTail = m_expressionState.addParenthesesTail(term);
     1568           
    9501569            // generate the body of the parentheses
    9511570            TermGenerationState parenthesesState(disjunction, state.checkedTotal);
    9521571            generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
    9531572
    954             Jump success = (term.quantityType == QuantifierFixedCount) ?
    955                 jump() :
    956                 branch32(NotEqual, index, Address(stackPointerRegister, (parenthesesFrameLocation * sizeof(void*))));
    957 
    958             // A failure AFTER the parens jumps here
    959             Label backtrackFromAfterParens(this);
    960 
    961             if (term.quantityType == QuantifierGreedy) {
    962                 // If this is -1 we have now tested with both with and without the parens.
    963                 loadFromFrame(parenthesesFrameLocation, indexTemporary);
    964                 state.jumpToBacktrack(branch32(Equal, indexTemporary, Imm32(-1)), this);
    965             } else if (term.quantityType == QuantifierNonGreedy) {
    966                 // If this is -1 we have now tested without the parens, now test with.
    967                 loadFromFrame(parenthesesFrameLocation, indexTemporary);
    968                 branch32(Equal, indexTemporary, Imm32(-1)).linkTo(nonGreedyTryParentheses, this);
    969             }
    970 
    971             parenthesesState.plantJumpToBacktrackIfExists(this);
    972             // A failure WITHIN the parens jumps here
    973             parenthesesState.linkAlternativeBacktracks(this);
    974             if (term.invertOrCapture)
    975                 store32(Imm32(-1), Address(output, (term.parentheses.subpatternId << 1) * sizeof(int)));
    976 
    977             if (term.quantityType == QuantifierGreedy)
    978                 storeToFrame(Imm32(-1), parenthesesFrameLocation);
    979             else
    980                 state.jumpToBacktrack(jump(), this);
    981 
    982             state.setBacktrackGenerated(backtrackFromAfterParens);
    983             if (term.quantityType == QuantifierNonGreedy)
    984                 nonGreedySkipParentheses.link(this);
    985             success.link(this);
    986 
     1573            // For non-fixed counts, backtrack if we didn't match anything.
     1574            if (term.quantityType != QuantifierFixedCount)
     1575                parenthesesTail->addAfterParenJump(branch32(Equal, index, Address(stackPointerRegister, (parenthesesFrameLocation * sizeof(void*)))));
     1576           
    9871577            // store the match end index
    988             if (term.invertOrCapture) {
     1578            if (term.capture()) {
    9891579                int inputOffset = state.inputOffset();
    9901580                if (inputOffset) {
     
    9951585                    store32(index, Address(output, ((term.parentheses.subpatternId << 1) + 1) * sizeof(int)));
    9961586            }
     1587           
     1588            parenthesesTail->processBacktracks(this, state, parenthesesState, nonGreedyTryParentheses, label());
     1589
     1590            parenthesesState.getBacktrackDestination().clear();
     1591           
     1592            if (term.quantityType == QuantifierNonGreedy)
     1593                nonGreedySkipParentheses.link(this);
    9971594        }
    9981595    }
     
    10331630
    10341631            parenthesesState.linkAlternativeBacktracks(this);
     1632
    10351633            // We get here if the alternative fails to match - fall through to the next iteration, or out of the loop.
    10361634
     
    10571655        int countCheckedAfterAssertion = state.checkedTotal - term.inputPosition;
    10581656
    1059         if (term.invertOrCapture) {
     1657        if (term.invert()) {
    10601658            // Inverted case
    10611659            storeToFrame(index, parenthesesFrameLocation);
     
    10691667            // Success! - which means - Fail!
    10701668            loadFromFrame(parenthesesFrameLocation, index);
    1071             state.jumpToBacktrack(jump(), this);
     1669            state.jumpToBacktrack(this);
    10721670
    10731671            // And fail means success.
    10741672            parenthesesState.linkAlternativeBacktracks(this);
     1673
    10751674            loadFromFrame(parenthesesFrameLocation, index);
    10761675
     
    10911690
    10921691            parenthesesState.linkAlternativeBacktracks(this);
     1692
    10931693            loadFromFrame(parenthesesFrameLocation, index);
    1094             state.jumpToBacktrack(jump(), this);
     1694            state.jumpToBacktrack(this);
    10951695
    10961696            success.link(this);
     
    12421842
    12431843            state.nextAlternative();
     1844            if (alternative->onceThrough() && state.alternativeValid())
     1845                state.clearBacktrack();
    12441846
    12451847            // if there are any more alternatives, plant the check for input before looping.
     
    12491851                    // We have handled non-repeating alternatives, jump to next iteration
    12501852                    // and loop over repeating alternatives.
    1251                     state.jumpToBacktrack(jump(), this);
     1853                    state.jumpToBacktrack(this);
    12521854                   
    12531855                    countToCheckForFirstAlternative = nextAlternative->m_minimumSize;
     
    12881890                        // If we get here, then the last input checked passed.
    12891891                        state.linkAlternativeBacktracks(this);
     1892
    12901893                        // No need to check if we can run the next alternative, since it is shorter -
    12911894                        // just update index.
     
    13021905                        // The next alternative is longer than the current one; check the difference.
    13031906                        state.linkAlternativeBacktracks(this);
     1907
    13041908                        notEnoughInputForPreviousAlternative.append(jumpIfNoAvailableInput(countToCheckForNextAlternative - countCheckedForCurrentAlternative));
    13051909                    } else { // CASE 3: Both alternatives are the same length.
     
    13251929            // If there are no alternatives that need repeating (all are marked 'onceThrough') then just link
    13261930            // the match failures to this point, and fall through to the return below.
    1327             state.linkAlternativeBacktracks(this);
     1931            state.linkAlternativeBacktracks(this, true);
     1932
    13281933            notEnoughInputForPreviousAlternative.link(this);
    13291934        } else {
     
    13451950            // First, deal with the cases where there was sufficient input to try the last alternative.
    13461951            if (incrementForNextIter > 0) // We need to check for more input anyway, fall through to the checking below.
    1347                 state.linkAlternativeBacktracks(this);
     1952                state.linkAlternativeBacktracks(this, true);
    13481953            else if (m_pattern.m_body->m_hasFixedSize && !incrementForNextIter) // No need to update anything, link these backtracks straight to the to pof the loop!
    1349                 state.linkAlternativeBacktracksTo(firstAlternativeInputChecked, this);
     1954                state.linkAlternativeBacktracksTo(this, firstAlternativeInputChecked, true);
    13501955            else { // no need to check the input, but we do have some bookkeeping to do first.
    1351                 state.linkAlternativeBacktracks(this);
     1956                state.linkAlternativeBacktracks(this, true);
    13521957
    13531958                // Where necessary update our preserved start position.
     
    14062011
    14072012        generateReturn();
     2013
     2014        m_expressionState.emitParenthesesTail(this);
     2015        m_expressionState.emitIndirectJumpTable(this);
     2016        m_expressionState.linkToNextIteration(this);
    14082017    }
    14092018
     
    14922101        LinkBuffer patchBuffer(this, globalData->executableAllocator.poolForSize(size()), 0);
    14932102
    1494         for (unsigned i = 0; i < m_backtrackRecords.size(); ++i)
    1495             patchBuffer.patch(m_backtrackRecords[i].dataLabel, patchBuffer.locationOf(m_backtrackRecords[i].backtrackLocation));
     2103        for (unsigned i = 0; i < m_expressionState.m_backtrackRecords.size(); ++i)
     2104            patchBuffer.patch(m_expressionState.m_backtrackRecords[i].dataLabel, patchBuffer.locationOf(m_expressionState.m_backtrackRecords[i].backtrackLocation));
    14962105
    14972106        jitObject.set(patchBuffer.finalizeCode());
     
    15022111    RegexPattern& m_pattern;
    15032112    bool m_shouldFallBack;
    1504     Vector<AlternativeBacktrackRecord> m_backtrackRecords;
     2113    GenerationState m_expressionState;
    15052114};
    15062115
     
    15152124
    15162125#endif
    1517 
    1518 
    1519 
    1520 
    1521 
  • trunk/JavaScriptCore/yarr/RegexPattern.h

    r73065 r73307  
    104104        TypeParentheticalAssertion,
    105105    } type;
    106     bool invertOrCapture;
     106    bool m_capture :1;
     107    bool m_invert :1;
    107108    union {
    108109        UChar patternCharacter;
     
    124125    PatternTerm(UChar ch)
    125126        : type(PatternTerm::TypePatternCharacter)
     127        , m_capture(false)
     128        , m_invert(false)
    126129    {
    127130        patternCharacter = ch;
     
    132135    PatternTerm(CharacterClass* charClass, bool invert)
    133136        : type(PatternTerm::TypeCharacterClass)
    134         , invertOrCapture(invert)
     137        , m_capture(false)
     138        , m_invert(invert)
    135139    {
    136140        characterClass = charClass;
     
    139143    }
    140144
    141     PatternTerm(Type type, unsigned subpatternId, PatternDisjunction* disjunction, bool invertOrCapture)
     145    PatternTerm(Type type, unsigned subpatternId, PatternDisjunction* disjunction, bool capture = false, bool invert = false)
    142146        : type(type)
    143         , invertOrCapture(invertOrCapture)
     147        , m_capture(capture)
     148        , m_invert(invert)
    144149    {
    145150        parentheses.disjunction = disjunction;
     
    153158    PatternTerm(Type type, bool invert = false)
    154159        : type(type)
    155         , invertOrCapture(invert)
     160        , m_capture(false)
     161        , m_invert(invert)
    156162    {
    157163        quantityType = QuantifierFixedCount;
     
    161167    PatternTerm(unsigned spatternId)
    162168        : type(TypeBackReference)
    163         , invertOrCapture(false)
     169        , m_capture(false)
     170        , m_invert(false)
    164171    {
    165172        backReferenceSubpatternId = spatternId;
     
    190197    bool invert()
    191198    {
    192         return invertOrCapture;
     199        return m_invert;
    193200    }
    194201
    195202    bool capture()
    196203    {
    197         return invertOrCapture;
     204        return m_capture;
    198205    }
    199206   
  • trunk/LayoutTests/ChangeLog

    r73302 r73307  
     12010-12-03  Michael Saboff  <msaboff@apple.com>
     2
     3        Reviewed by Gavin Barraclough
     4
     5        Added new tests to support changes to Regexp JIT code handling
     6        of parentheses.  Tests focused on backtracking and nested
     7        subexpressions.
     8        https://bugs.webkit.org/show_bug.cgi?id=50295
     9
     10        * fast/regex/parentheses-expected.txt: Added.
     11        * fast/regex/parentheses.html: Added.
     12        * fast/regex/script-tests/parentheses.js: Added.
     13
    1142010-12-03  Chris Guillory  <chris.guillory@google.com>
    215
Note: See TracChangeset for help on using the changeset viewer.