]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wrec/WRECGenerator.cpp
JavaScriptCore-621.1.tar.gz
[apple/javascriptcore.git] / wrec / WRECGenerator.cpp
diff --git a/wrec/WRECGenerator.cpp b/wrec/WRECGenerator.cpp
deleted file mode 100644 (file)
index 7105984..0000000
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "WREC.h"
-
-#if ENABLE(WREC)
-
-#include "CharacterClassConstructor.h"
-#include "Interpreter.h"
-#include "WRECFunctors.h"
-#include "WRECParser.h"
-#include "pcre_internal.h"
-
-using namespace WTF;
-
-namespace JSC { namespace WREC {
-
-void Generator::generateEnter()
-{
-#if CPU(X86)
-    // On x86 edi & esi are callee preserved registers.
-    push(X86Registers::edi);
-    push(X86Registers::esi);
-    
-#if COMPILER(MSVC)
-    // Move the arguments into registers.
-    peek(input, 3);
-    peek(index, 4);
-    peek(length, 5);
-    peek(output, 6);
-#else
-    // On gcc the function is regparm(3), so the input, index, and length registers
-    // (eax, edx, and ecx respectively) already contain the appropriate values.
-    // Just load the fourth argument (output) into edi
-    peek(output, 3);
-#endif
-#endif
-}
-
-void Generator::generateReturnSuccess()
-{
-    ASSERT(returnRegister != index);
-    ASSERT(returnRegister != output);
-
-    // Set return value.
-    pop(returnRegister); // match begin
-    store32(returnRegister, output);
-    store32(index, Address(output, 4)); // match end
-    
-    // Restore callee save registers.
-#if CPU(X86)
-    pop(X86Registers::esi);
-    pop(X86Registers::edi);
-#endif
-    ret();
-}
-
-void Generator::generateSaveIndex()
-{
-    push(index);
-}
-
-void Generator::generateIncrementIndex(Jump* failure)
-{
-    peek(index);
-    if (failure)
-        *failure = branch32(Equal, length, index);
-    add32(Imm32(1), index);
-    poke(index);
-}
-
-void Generator::generateLoadCharacter(JumpList& failures)
-{
-    failures.append(branch32(Equal, length, index));
-    load16(BaseIndex(input, index, TimesTwo), character);
-}
-
-// For the sake of end-of-line assertions, we treat one-past-the-end as if it
-// were part of the input string.
-void Generator::generateJumpIfNotEndOfInput(Label target)
-{
-    branch32(LessThanOrEqual, index, length, target);
-}
-
-void Generator::generateReturnFailure()
-{
-    pop();
-    move(Imm32(-1), returnRegister);
-
-#if CPU(X86)
-    pop(X86Registers::esi);
-    pop(X86Registers::edi);
-#endif
-    ret();
-}
-
-void Generator::generateBacktrack1()
-{
-    sub32(Imm32(1), index);
-}
-
-void Generator::generateBacktrackBackreference(unsigned subpatternId)
-{
-    sub32(Address(output, (2 * subpatternId + 1) * sizeof(int)), index);
-    add32(Address(output, (2 * subpatternId) * sizeof(int)), index);
-}
-
-void Generator::generateBackreferenceQuantifier(JumpList& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max)
-{
-    GenerateBackreferenceFunctor functor(subpatternId);
-
-    load32(Address(output, (2 * subpatternId) * sizeof(int)), character);
-    Jump skipIfEmpty = branch32(Equal, Address(output, ((2 * subpatternId) + 1) * sizeof(int)), character);
-
-    ASSERT(quantifierType == Quantifier::Greedy || quantifierType == Quantifier::NonGreedy);
-    if (quantifierType == Quantifier::Greedy)
-        generateGreedyQuantifier(failures, functor, min, max);
-    else
-        generateNonGreedyQuantifier(failures, functor, min, max);
-
-    skipIfEmpty.link(this);
-}
-
-void Generator::generateNonGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max)
-{
-    JumpList atomFailedList;
-    JumpList alternativeFailedList;
-
-    // (0) Setup: Save, then init repeatCount.
-    push(repeatCount);
-    move(Imm32(0), repeatCount);
-    Jump start = jump();
-
-    // (4) Quantifier failed: No more atom reading possible.
-    Label quantifierFailed(this);
-    pop(repeatCount);
-    failures.append(jump()); 
-
-    // (3) Alternative failed: If we can, read another atom, then fall through to (2) to try again.
-    Label alternativeFailed(this);
-    pop(index);
-    if (max != Quantifier::Infinity)
-        branch32(Equal, repeatCount, Imm32(max), quantifierFailed);
-
-    // (1) Read an atom.
-    if (min)
-        start.link(this);
-    Label readAtom(this);
-    functor.generateAtom(this, atomFailedList);
-    atomFailedList.linkTo(quantifierFailed, this);
-    add32(Imm32(1), repeatCount);
-    
-    // (2) Keep reading if we're under the minimum.
-    if (min > 1)
-        branch32(LessThan, repeatCount, Imm32(min), readAtom);
-
-    // (3) Test the rest of the alternative.
-    if (!min)
-        start.link(this);
-    push(index);
-    m_parser.parseAlternative(alternativeFailedList);
-    alternativeFailedList.linkTo(alternativeFailed, this);
-
-    pop();
-    pop(repeatCount);
-}
-
-void Generator::generateGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max)
-{
-    if (!max)
-        return;
-
-    JumpList doneReadingAtomsList;
-    JumpList alternativeFailedList;
-
-    // (0) Setup: Save, then init repeatCount.
-    push(repeatCount);
-    move(Imm32(0), repeatCount);
-
-    // (1) Greedily read as many copies of the atom as possible, then jump to (2).
-    Label readAtom(this);
-    functor.generateAtom(this, doneReadingAtomsList);
-    add32(Imm32(1), repeatCount);
-    if (max == Quantifier::Infinity)
-        jump(readAtom);
-    else if (max == 1)
-        doneReadingAtomsList.append(jump());
-    else {
-        branch32(NotEqual, repeatCount, Imm32(max), readAtom);
-        doneReadingAtomsList.append(jump());
-    }
-
-    // (5) Quantifier failed: No more backtracking possible.
-    Label quantifierFailed(this);
-    pop(repeatCount);
-    failures.append(jump()); 
-
-    // (4) Alternative failed: Backtrack, then fall through to (2) to try again.
-    Label alternativeFailed(this);
-    pop(index);
-    functor.backtrack(this);
-    sub32(Imm32(1), repeatCount);
-
-    // (2) Verify that we have enough atoms.
-    doneReadingAtomsList.link(this);
-    branch32(LessThan, repeatCount, Imm32(min), quantifierFailed);
-
-    // (3) Test the rest of the alternative.
-    push(index);
-    m_parser.parseAlternative(alternativeFailedList);
-    alternativeFailedList.linkTo(alternativeFailed, this);
-
-    pop();
-    pop(repeatCount);
-}
-
-void Generator::generatePatternCharacterSequence(JumpList& failures, int* sequence, size_t count)
-{
-    for (size_t i = 0; i < count;) {
-        if (i < count - 1) {
-            if (generatePatternCharacterPair(failures, sequence[i], sequence[i + 1])) {
-                i += 2;
-                continue;
-            }
-        }
-
-        generatePatternCharacter(failures, sequence[i]);
-        ++i;
-    }
-}
-
-bool Generator::generatePatternCharacterPair(JumpList& failures, int ch1, int ch2)
-{
-    if (m_parser.ignoreCase()) {
-        // Non-trivial case folding requires more than one test, so we can't
-        // test as a pair with an adjacent character.
-        if (!isASCII(ch1) && Unicode::toLower(ch1) != Unicode::toUpper(ch1))
-            return false;
-        if (!isASCII(ch2) && Unicode::toLower(ch2) != Unicode::toUpper(ch2))
-            return false;
-    }
-
-    // Optimistically consume 2 characters.
-    add32(Imm32(2), index);
-    failures.append(branch32(GreaterThan, index, length));
-
-    // Load the characters we just consumed, offset -2 characters from index.
-    load32(BaseIndex(input, index, TimesTwo, -2 * 2), character);
-
-    if (m_parser.ignoreCase()) {
-        // Convert ASCII alphabet characters to upper case before testing for
-        // equality. (ASCII non-alphabet characters don't require upper-casing
-        // because they have no uppercase equivalents. Unicode characters don't
-        // require upper-casing because we only handle Unicode characters whose
-        // upper and lower cases are equal.)
-        int ch1Mask = 0;
-        if (isASCIIAlpha(ch1)) {
-            ch1 |= 32;
-            ch1Mask = 32;
-        }
-
-        int ch2Mask = 0;
-        if (isASCIIAlpha(ch2)) {
-            ch2 |= 32;
-            ch2Mask = 32;
-        }
-
-        int mask = ch1Mask | (ch2Mask << 16);
-        if (mask)
-            or32(Imm32(mask), character);
-    }
-    int pair = ch1 | (ch2 << 16);
-
-    failures.append(branch32(NotEqual, character, Imm32(pair)));
-    return true;
-}
-
-void Generator::generatePatternCharacter(JumpList& failures, int ch)
-{
-    generateLoadCharacter(failures);
-
-    // used for unicode case insensitive
-    bool hasUpper = false;
-    Jump isUpper;
-    
-    // if case insensitive match
-    if (m_parser.ignoreCase()) {
-        UChar lower, upper;
-        
-        // check for ascii case sensitive characters
-        if (isASCIIAlpha(ch)) {
-            or32(Imm32(32), character);
-            ch |= 32;
-        } else if (!isASCII(ch) && ((lower = Unicode::toLower(ch)) != (upper = Unicode::toUpper(ch)))) {
-            // handle unicode case sentitive characters - branch to success on upper
-            isUpper = branch32(Equal, character, Imm32(upper));
-            hasUpper = true;
-            ch = lower;
-        }
-    }
-    
-    // checks for ch, or lower case version of ch, if insensitive
-    failures.append(branch32(NotEqual, character, Imm32((unsigned short)ch)));
-
-    if (m_parser.ignoreCase() && hasUpper) {
-        // for unicode case insensitive matches, branch here if upper matches.
-        isUpper.link(this);
-    }
-    
-    // on success consume the char
-    add32(Imm32(1), index);
-}
-
-void Generator::generateCharacterClassInvertedRange(JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount)
-{
-    do {
-        // pick which range we're going to generate
-        int which = count >> 1;
-        char lo = ranges[which].begin;
-        char hi = ranges[which].end;
-        
-        // check if there are any ranges or matches below lo.  If not, just jl to failure -
-        // if there is anything else to check, check that first, if it falls through jmp to failure.
-        if ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
-            Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo));
-            
-            // generate code for all ranges before this one
-            if (which)
-                generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount);
-            
-            while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
-                matchDest.append(branch32(Equal, character, Imm32((unsigned short)matches[*matchIndex])));
-                ++*matchIndex;
-            }
-            failures.append(jump());
-
-            loOrAbove.link(this);
-        } else if (which) {
-            Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo));
-
-            generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount);
-            failures.append(jump());
-
-            loOrAbove.link(this);
-        } else
-            failures.append(branch32(LessThan, character, Imm32((unsigned short)lo)));
-
-        while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi))
-            ++*matchIndex;
-
-        matchDest.append(branch32(LessThanOrEqual, character, Imm32((unsigned short)hi)));
-        // fall through to here, the value is above hi.
-
-        // shuffle along & loop around if there are any more matches to handle.
-        unsigned next = which + 1;
-        ranges += next;
-        count -= next;
-    } while (count);
-}
-
-void Generator::generateCharacterClassInverted(JumpList& matchDest, const CharacterClass& charClass)
-{
-    Jump unicodeFail;
-    if (charClass.numMatchesUnicode || charClass.numRangesUnicode) {
-        Jump isAscii = branch32(LessThanOrEqual, character, Imm32(0x7f));
-    
-        if (charClass.numMatchesUnicode) {
-            for (unsigned i = 0; i < charClass.numMatchesUnicode; ++i) {
-                UChar ch = charClass.matchesUnicode[i];
-                matchDest.append(branch32(Equal, character, Imm32(ch)));
-            }
-        }
-        
-        if (charClass.numRangesUnicode) {
-            for (unsigned i = 0; i < charClass.numRangesUnicode; ++i) {
-                UChar lo = charClass.rangesUnicode[i].begin;
-                UChar hi = charClass.rangesUnicode[i].end;
-                
-                Jump below = branch32(LessThan, character, Imm32(lo));
-                matchDest.append(branch32(LessThanOrEqual, character, Imm32(hi)));
-                below.link(this);
-            }
-        }
-
-        unicodeFail = jump();
-        isAscii.link(this);
-    }
-
-    if (charClass.numRanges) {
-        unsigned matchIndex = 0;
-        JumpList failures; 
-        generateCharacterClassInvertedRange(failures, matchDest, charClass.ranges, charClass.numRanges, &matchIndex, charClass.matches, charClass.numMatches);
-        while (matchIndex < charClass.numMatches)
-            matchDest.append(branch32(Equal, character, Imm32((unsigned short)charClass.matches[matchIndex++])));
-
-        failures.link(this);
-    } else if (charClass.numMatches) {
-        // optimization: gather 'a','A' etc back together, can mask & test once.
-        Vector<char> matchesAZaz;
-
-        for (unsigned i = 0; i < charClass.numMatches; ++i) {
-            char ch = charClass.matches[i];
-            if (m_parser.ignoreCase()) {
-                if (isASCIILower(ch)) {
-                    matchesAZaz.append(ch);
-                    continue;
-                }
-                if (isASCIIUpper(ch))
-                    continue;
-            }
-            matchDest.append(branch32(Equal, character, Imm32((unsigned short)ch)));
-        }
-
-        if (unsigned countAZaz = matchesAZaz.size()) {
-            or32(Imm32(32), character);
-            for (unsigned i = 0; i < countAZaz; ++i)
-                matchDest.append(branch32(Equal, character, Imm32(matchesAZaz[i])));
-        }
-    }
-
-    if (charClass.numMatchesUnicode || charClass.numRangesUnicode)
-        unicodeFail.link(this);
-}
-
-void Generator::generateCharacterClass(JumpList& failures, const CharacterClass& charClass, bool invert)
-{
-    generateLoadCharacter(failures);
-
-    if (invert)
-        generateCharacterClassInverted(failures, charClass);
-    else {
-        JumpList successes;
-        generateCharacterClassInverted(successes, charClass);
-        failures.append(jump());
-        successes.link(this);
-    }
-    
-    add32(Imm32(1), index);
-}
-
-void Generator::generateParenthesesAssertion(JumpList& failures)
-{
-    JumpList disjunctionFailed;
-
-    push(index);
-    m_parser.parseDisjunction(disjunctionFailed);
-    Jump success = jump();
-
-    disjunctionFailed.link(this);
-    pop(index);
-    failures.append(jump());
-
-    success.link(this);
-    pop(index);
-}
-
-void Generator::generateParenthesesInvertedAssertion(JumpList& failures)
-{
-    JumpList disjunctionFailed;
-
-    push(index);
-    m_parser.parseDisjunction(disjunctionFailed);
-
-    // If the disjunction succeeded, the inverted assertion failed.
-    pop(index);
-    failures.append(jump());
-
-    // If the disjunction failed, the inverted assertion succeeded.
-    disjunctionFailed.link(this);
-    pop(index);
-}
-
-void Generator::generateParenthesesNonGreedy(JumpList& failures, Label start, Jump success, Jump fail)
-{
-    jump(start);
-    success.link(this);
-    failures.append(fail);
-}
-
-Generator::Jump Generator::generateParenthesesResetTrampoline(JumpList& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter)
-{
-    Jump skip = jump();
-    newFailures.link(this);
-    for (unsigned i = subpatternIdBefore + 1; i <= subpatternIdAfter; ++i) {
-        store32(Imm32(-1), Address(output, (2 * i) * sizeof(int)));
-        store32(Imm32(-1), Address(output, (2 * i + 1) * sizeof(int)));
-    }
-    
-    Jump newFailJump = jump();
-    skip.link(this);
-    
-    return newFailJump;
-}
-
-void Generator::generateAssertionBOL(JumpList& failures)
-{
-    if (m_parser.multiline()) {
-        JumpList previousIsNewline;
-
-        // begin of input == success
-        previousIsNewline.append(branch32(Equal, index, Imm32(0)));
-
-        // now check prev char against newline characters.
-        load16(BaseIndex(input, index, TimesTwo, -2), character);
-        generateCharacterClassInverted(previousIsNewline, CharacterClass::newline());
-
-        failures.append(jump());
-
-        previousIsNewline.link(this);
-    } else
-        failures.append(branch32(NotEqual, index, Imm32(0)));
-}
-
-void Generator::generateAssertionEOL(JumpList& failures)
-{
-    if (m_parser.multiline()) {
-        JumpList nextIsNewline;
-
-        generateLoadCharacter(nextIsNewline); // end of input == success
-        generateCharacterClassInverted(nextIsNewline, CharacterClass::newline());
-        failures.append(jump());
-        nextIsNewline.link(this);
-    } else {
-        failures.append(branch32(NotEqual, length, index));
-    }
-}
-
-void Generator::generateAssertionWordBoundary(JumpList& failures, bool invert)
-{
-    JumpList wordBoundary;
-    JumpList notWordBoundary;
-
-    // (1) Check if the previous value was a word char
-
-    // (1.1) check for begin of input
-    Jump atBegin = branch32(Equal, index, Imm32(0));
-    // (1.2) load the last char, and chck if is word character
-    load16(BaseIndex(input, index, TimesTwo, -2), character);
-    JumpList previousIsWord;
-    generateCharacterClassInverted(previousIsWord, CharacterClass::wordchar());
-    // (1.3) if we get here, previous is not a word char
-    atBegin.link(this);
-
-    // (2) Handle situation where previous was NOT a \w
-
-    generateLoadCharacter(notWordBoundary);
-    generateCharacterClassInverted(wordBoundary, CharacterClass::wordchar());
-    // (2.1) If we get here, neither chars are word chars
-    notWordBoundary.append(jump());
-
-    // (3) Handle situation where previous was a \w
-
-    // (3.0) link success in first match to here
-    previousIsWord.link(this);
-    generateLoadCharacter(wordBoundary);
-    generateCharacterClassInverted(notWordBoundary, CharacterClass::wordchar());
-    // (3.1) If we get here, this is an end of a word, within the input.
-    
-    // (4) Link everything up
-    
-    if (invert) {
-        // handle the fall through case
-        wordBoundary.append(jump());
-    
-        // looking for non word boundaries, so link boundary fails to here.
-        notWordBoundary.link(this);
-
-        failures.append(wordBoundary);
-    } else {
-        // looking for word boundaries, so link successes here.
-        wordBoundary.link(this);
-        
-        failures.append(notWordBoundary);
-    }
-}
-
-void Generator::generateBackreference(JumpList& failures, unsigned subpatternId)
-{
-    push(index);
-    push(repeatCount);
-
-    // get the start pos of the backref into repeatCount (multipurpose!)
-    load32(Address(output, (2 * subpatternId) * sizeof(int)), repeatCount);
-
-    Jump skipIncrement = jump();
-    Label topOfLoop(this);
-
-    add32(Imm32(1), index);
-    add32(Imm32(1), repeatCount);
-    skipIncrement.link(this);
-
-    // check if we're at the end of backref (if we are, success!)
-    Jump endOfBackRef = branch32(Equal, Address(output, ((2 * subpatternId) + 1) * sizeof(int)), repeatCount);
-
-    load16(BaseIndex(input, repeatCount, MacroAssembler::TimesTwo), character);
-
-    // check if we've run out of input (this would be a can o'fail)
-    Jump endOfInput = branch32(Equal, length, index);
-
-    branch16(Equal, BaseIndex(input, index, TimesTwo), character, topOfLoop);
-
-    endOfInput.link(this);
-
-    // Failure
-    pop(repeatCount);
-    pop(index);
-    failures.append(jump());
-
-    // Success
-    endOfBackRef.link(this);
-    pop(repeatCount);
-    pop();
-}
-
-void Generator::terminateAlternative(JumpList& successes, JumpList& failures)
-{
-    successes.append(jump());
-    
-    failures.link(this);
-    peek(index);
-}
-
-void Generator::terminateDisjunction(JumpList& successes)
-{
-    successes.link(this);
-}
-
-} } // namespace JSC::WREC
-
-#endif // ENABLE(WREC)