Ignore:
Timestamp:
Jul 7, 2010, 12:04:46 AM (15 years ago)
Author:
[email protected]
Message:

Refactored string parsing inside the lexer
https://bugs.webkit.org/show_bug.cgi?id=41606

Reviewed by Oliver Hunt.

Does not use goto. Although the last sunspider
parse-only tests yields 1.044x speedup, I think the
patch can have a slight improvement at most.

  • parser/Lexer.cpp:

(JSC::singleEscape):
(JSC::Lexer::parseString):
(JSC::Lexer::lex):

  • parser/Lexer.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/parser/Lexer.cpp

    r62449 r62628  
    358358        case 'r':
    359359            return 0x0D;
     360        case '\\':
     361            return '\\';
     362        case '\'':
     363            return '\'';
     364        case '"':
     365            return '"';
    360366        default:
    361             return c;
     367            return 0;
    362368    }
    363369}
     
    380386    ASSERT(c <= USHRT_MAX);
    381387    record16(UChar(static_cast<unsigned short>(c)));
     388}
     389
     390ALWAYS_INLINE bool Lexer::parseString(void* lvalp)
     391{
     392    int stringQuoteCharacter = m_current;
     393    shift();
     394
     395    const UChar* stringStart = currentCharacter();
     396
     397    while (m_current != stringQuoteCharacter) {
     398        if (UNLIKELY(m_current == '\\')) {
     399            if (stringStart != currentCharacter())
     400                m_buffer16.append(stringStart, currentCharacter() - stringStart);
     401            shift();
     402
     403            int escape = singleEscape(m_current);
     404
     405            // Most common escape sequences first
     406            if (escape) {
     407                record16(escape);
     408                shift();
     409            } else if (UNLIKELY(isLineTerminator(m_current)))
     410                shiftLineTerminator();
     411            else if (m_current == 'x') {
     412                shift();
     413                if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
     414                    int prev = m_current;
     415                    shift();
     416                    record16(convertHex(prev, m_current));
     417                    shift();
     418                } else
     419                    record16('x');
     420            } else if (m_current == 'u') {
     421                shift();
     422                int character = getUnicodeCharacter();
     423                if (character != -1)
     424                    record16(character);
     425                else if (m_current == stringQuoteCharacter)
     426                    record16('u');
     427                else // Only stringQuoteCharacter allowed after \u
     428                    return false;
     429            } else if (isASCIIOctalDigit(m_current)) {
     430                // Octal character sequences
     431                int character1 = m_current;
     432                shift();
     433                if (isASCIIOctalDigit(m_current)) {
     434                    // Two octal characters
     435                    int character2 = m_current;
     436                    shift();
     437                    if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
     438                        record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0');
     439                        shift();
     440                    } else
     441                        record16((character1 - '0') * 8 + character2 - '0');
     442                } else
     443                    record16(character1 - '0');
     444            } else if (m_current != -1) {
     445                record16(m_current);
     446                shift();
     447            } else
     448                return false;
     449
     450            stringStart = currentCharacter();
     451            continue;
     452        } else if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
     453            // New-line or end of input is not allowed
     454            if (UNLIKELY(isLineTerminator(m_current)) || UNLIKELY(m_current == -1))
     455                return false;
     456            // Anything else is just a normal character
     457        }
     458        shift();
     459    }
     460
     461    if (currentCharacter() != stringStart)
     462        m_buffer16.append(stringStart, currentCharacter() - stringStart);
     463    reinterpret_cast<YYSTYPE*>(lvalp)->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
     464    m_buffer16.resize(0);
     465    return true;
    382466}
    383467
     
    402486        if (!m_terminator && !m_delimited && !m_isReparsing) {
    403487            // automatic semicolon insertion if program incomplete
    404             token = ';';
    405488            goto doneSemicolon;
    406489        }
     
    409492
    410493    m_delimited = false;
    411     ASSERT(m_current >= 0);
    412 
    413     if (m_current < 128) {
    414         ASSERT(isASCII(m_current));
     494
     495    if (isASCII(m_current)) {
     496        ASSERT(m_current >= 0 && m_current < 128);
    415497
    416498        switch (AsciiCharacters[m_current]) {
     
    634716            goto startNumber;
    635717        case CharacterQuote:
    636             goto startString;
     718            if (UNLIKELY(!parseString(lvalp)))
     719                goto returnError;
     720            shift();
     721            m_delimited = false;
     722            token = STRING;
     723            break;
    637724        case CharacterAlpha:
    638725            ASSERT(isIdentStart(m_current));
     
    656743    } else {
    657744        // Rare characters
    658         ASSERT(!isASCII(m_current));
    659745
    660746        if (isNonASCIIIdentStart(m_current))
     
    664750            m_atLineStart = true;
    665751            m_terminator = true;
    666             if (lastTokenWasRestrKeyword()) {
    667                 token = ';';
     752            if (lastTokenWasRestrKeyword())
    668753                goto doneSemicolon;
    669             }
    670754            goto start;
    671755        }
     
    675759    m_atLineStart = false;
    676760    goto returnToken;
    677 
    678 startString: {
    679     int stringQuoteCharacter = m_current;
    680     shift();
    681 
    682     const UChar* stringStart = currentCharacter();
    683     while (m_current != stringQuoteCharacter) {
    684         // Fast check for characters that require special handling.
    685         // Catches -1, \n, \r, \, 0x2028, and 0x2029 as efficiently
    686         // as possible, and lets through all common ASCII characters.
    687         if (UNLIKELY(m_current == '\\') || UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
    688             m_buffer16.append(stringStart, currentCharacter() - stringStart);
    689             goto inString;
    690         }
    691         shift();
    692     }
    693     lvalp->ident = makeIdentifier(stringStart, currentCharacter() - stringStart);
    694     shift();
    695     m_atLineStart = false;
    696     m_delimited = false;
    697     token = STRING;
    698     goto returnToken;
    699 
    700 inString:
    701     while (m_current != stringQuoteCharacter) {
    702         if (m_current == '\\')
    703             goto inStringEscapeSequence;
    704         if (UNLIKELY(isLineTerminator(m_current)))
    705             goto returnError;
    706         if (UNLIKELY(m_current == -1))
    707             goto returnError;
    708         record16(m_current);
    709         shift();
    710     }
    711     goto doneString;
    712 
    713 inStringEscapeSequence:
    714     shift();
    715     if (m_current == 'x') {
    716         shift();
    717         if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
    718             int prev = m_current;
    719             shift();
    720             record16(convertHex(prev, m_current));
    721             shift();
    722             goto inString;
    723         }
    724         record16('x');
    725         if (m_current == stringQuoteCharacter)
    726             goto doneString;
    727         goto inString;
    728     }
    729     if (m_current == 'u') {
    730         shift();
    731         token = getUnicodeCharacter();
    732         if (token != -1) {
    733             record16(token);
    734             goto inString;
    735         }
    736         if (m_current == stringQuoteCharacter) {
    737             record16('u');
    738             goto doneString;
    739         }
    740         goto returnError;
    741     }
    742     if (isASCIIOctalDigit(m_current)) {
    743         int char1 = m_current;
    744         shift();
    745         if (char1 >= '0' && char1 <= '3' && isASCIIOctalDigit(m_current) && isASCIIOctalDigit(peek(1))) {
    746             int char2 = m_current;
    747             shift();
    748             record16((char1 - '0') * 64 + (char2 - '0') * 8 + m_current - '0');
    749             shift();
    750             goto inString;
    751         }
    752         if (isASCIIOctalDigit(m_current)) {
    753             record16((char1 - '0') * 8 + m_current - '0');
    754             shift();
    755             goto inString;
    756         }
    757         record16(char1 - '0');
    758         goto inString;
    759     }
    760     if (isLineTerminator(m_current)) {
    761         shiftLineTerminator();
    762         goto inString;
    763     }
    764     if (m_current == -1)
    765         goto returnError;
    766     record16(singleEscape(m_current));
    767     shift();
    768     goto inString;
    769 }
    770761
    771762startIdentifierWithBackslash: {
     
    1004995    const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident);
    1005996    token = entry ? entry->lexerValue() : static_cast<int>(IDENT);
    1006     goto returnToken;
    1007 }
    1008 
    1009 doneString:
    1010     // Atomize constant strings in case they're later used in property lookup.
    1011     shift();
    1012     m_atLineStart = false;
    1013     m_delimited = false;
    1014     lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
    1015     m_buffer16.resize(0);
    1016     token = STRING;
    1017997
    1018998    // Fall through into returnToken.
     999}
    10191000
    10201001returnToken: {
Note: See TracChangeset for help on using the changeset viewer.