Changeset 99812 in webkit


Ignore:
Timestamp:
Nov 9, 2011 8:49:01 PM (12 years ago)
Author:
msaboff@apple.com
Message:

Towards 8 Bit Strings: Templatize JSC::LiteralParser class by character type
https://bugs.webkit.org/show_bug.cgi?id=71862

Changed LiteralParser to be templatized of character type.

Moved five enums out of class definition to work around a clang compiler defect.

Added lexIdentifier templated method to break out character specific versions.
Added static setParserTokenString templated method to handle setting approriately
sized string pointer.

To keep code in LiteralParser.cpp and keep LiteralParser.h small, the two
flavors of LiteralParser are explicitly instantiated at the end of
LiteralParser.cpp.

Reviewed by Oliver Hunt.

  • API/JSValueRef.cpp:

(JSValueMakeFromJSONString):

(JSC::Interpreter::callEval):
(JSC::Interpreter::execute):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::globalFuncEval):

  • runtime/JSONObject.cpp:

(JSC::JSONProtoFuncParse):

  • runtime/LiteralParser.cpp:

(JSC::isJSONWhiteSpace):
(JSC::::tryJSONPParse):
(JSC::::makeIdentifier):
(JSC::::Lexer::lex):
(JSC::::Lexer::lexIdentifier):
(JSC::::Lexer::next):
(JSC::LChar):
(JSC::UChar):
(JSC::isSafeStringCharacter):
(JSC::::Lexer::lexString):
(JSC::::Lexer::lexNumber):
(JSC::::parse):

  • runtime/LiteralParser.h:

(JSC::LiteralParser::LiteralParser):
(JSC::LiteralParser::getErrorMessage):
(JSC::LiteralParser::tryLiteralParse):
(JSC::LiteralParser::Lexer::Lexer):
(JSC::LiteralParser::Lexer::currentToken):
(JSC::LiteralParser::Lexer::getErrorMessage):

  • runtime/UString.h:

(JSC::LChar):
(JSC::UChar):

  • wtf/text/StringBuilder.cpp:

(WTF::StringBuilder::append):

  • wtf/text/StringBuilder.h:

(WTF::StringBuilder::append):

Location:
trunk/Source/JavaScriptCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSValueRef.cpp

    r99312 r99812  
    236236    APIEntryShim entryShim(exec);
    237237    UString str = string->ustring();
    238     LiteralParser parser(exec, str.characters(), str.length(), LiteralParser::StrictJSON);
     238    if (str.is8Bit()) {
     239        LiteralParser<LChar> parser(exec, str.characters8(), str.length(), StrictJSON);
     240        return toRef(exec, parser.tryLiteralParse());
     241    }
     242    LiteralParser<UChar> parser(exec, str.characters16(), str.length(), StrictJSON);
    239243    return toRef(exec, parser.tryLiteralParse());
    240244}
  • trunk/Source/JavaScriptCore/ChangeLog

    r99810 r99812  
     12011-11-09  Michael Saboff  <msaboff@apple.com>
     2
     3        Towards 8 Bit Strings: Templatize JSC::LiteralParser class by character type
     4        https://bugs.webkit.org/show_bug.cgi?id=71862
     5
     6        Changed LiteralParser to be templatized of character type.
     7
     8        Moved five enums out of class definition to work around a clang compiler defect.
     9
     10        Added lexIdentifier templated method to break out character specific versions.
     11        Added static setParserTokenString templated method to handle setting approriately
     12        sized string pointer.
     13
     14        To keep code in LiteralParser.cpp and keep LiteralParser.h small, the two
     15        flavors of LiteralParser are explicitly instantiated at the end of
     16        LiteralParser.cpp.
     17
     18        Reviewed by Oliver Hunt.
     19
     20        * API/JSValueRef.cpp:
     21        (JSValueMakeFromJSONString):
     22        * JavaScriptCore.exp:
     23        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
     24        * interpreter/Interpreter.cpp:
     25        (JSC::Interpreter::callEval):
     26        (JSC::Interpreter::execute):
     27        * runtime/JSGlobalObjectFunctions.cpp:
     28        (JSC::globalFuncEval):
     29        * runtime/JSONObject.cpp:
     30        (JSC::JSONProtoFuncParse):
     31        * runtime/LiteralParser.cpp:
     32        (JSC::isJSONWhiteSpace):
     33        (JSC::::tryJSONPParse):
     34        (JSC::::makeIdentifier):
     35        (JSC::::Lexer::lex):
     36        (JSC::::Lexer::lexIdentifier):
     37        (JSC::::Lexer::next):
     38        (JSC::LChar):
     39        (JSC::UChar):
     40        (JSC::isSafeStringCharacter):
     41        (JSC::::Lexer::lexString):
     42        (JSC::::Lexer::lexNumber):
     43        (JSC::::parse):
     44        * runtime/LiteralParser.h:
     45        (JSC::LiteralParser::LiteralParser):
     46        (JSC::LiteralParser::getErrorMessage):
     47        (JSC::LiteralParser::tryLiteralParse):
     48        (JSC::LiteralParser::Lexer::Lexer):
     49        (JSC::LiteralParser::Lexer::currentToken):
     50        (JSC::LiteralParser::Lexer::getErrorMessage):
     51        * runtime/UString.h:
     52        (JSC::LChar):
     53        (JSC::UChar):
     54        * wtf/text/StringBuilder.cpp:
     55        (WTF::StringBuilder::append):
     56        * wtf/text/StringBuilder.h:
     57        (WTF::StringBuilder::append):
     58
    1592011-11-09  Filip Pizlo  <fpizlo@apple.com>
    260
  • trunk/Source/JavaScriptCore/JavaScriptCore.exp

    r99779 r99812  
    411411__ZN3WTF13StringBuilder11shrinkToFitEv
    412412__ZN3WTF13StringBuilder15reserveCapacityEj
    413 __ZN3WTF13StringBuilder6appendEPKcj
     413__ZN3WTF13StringBuilder6appendEPKhj
    414414__ZN3WTF13StringBuilder6appendEPKtj
    415415__ZN3WTF13StringBuilder6resizeEj
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def

    r99779 r99812  
    6363    ?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z
    6464    ?allocateSlowCase@AllocationSpace@JSC@@AAEPAXAAUSizeClass@MarkedSpace@2@@Z
    65     ?append@StringBuilder@WTF@@QAEXPBDI@Z
     65    ?append@StringBuilder@WTF@@QAEXPBEI@Z
    6666    ?append@StringBuilder@WTF@@QAEXPB_WI@Z
    6767    ?ascii@UString@JSC@@QBE?AVCString@WTF@@XZ
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r99618 r99812  
    446446            // FIXME: We can use the preparser in strict mode, we just need additional logic
    447447            // to prevent duplicates.
    448             LiteralParser preparser(callFrame, programSource.characters(), programSource.length(), LiteralParser::NonStrictJSON);
    449             if (JSValue parsedObject = preparser.tryLiteralParse())
    450                 return parsedObject;
     448            if (programSource.is8Bit()) {
     449                LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
     450                if (JSValue parsedObject = preparser.tryLiteralParse())
     451                    return parsedObject;
     452            } else {
     453                LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
     454                if (JSValue parsedObject = preparser.tryLiteralParse())
     455                    return parsedObject;               
     456            }
    451457        }
    452458
     
    780786
    781787    DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
    782     LiteralParser literalParser(callFrame, program->source().data(), program->source().length(), LiteralParser::JSONP);
    783     Vector<LiteralParser::JSONPData> JSONPData;
    784     if (literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->supportsRichSourceInfo())) {
     788    Vector<JSONPData> JSONPData;
     789    bool parseResult;
     790    const UString programSource = program->source().toString();
     791    if (programSource.is8Bit()) {
     792        LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
     793        parseResult = literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->supportsRichSourceInfo());
     794    } else {
     795        LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
     796        parseResult = literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->supportsRichSourceInfo());       
     797    }
     798
     799    if (parseResult) {
    785800        JSGlobalObject* globalObject = scopeChain->globalObject.get();
    786801        JSValue result;
    787802        for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
    788             Vector<LiteralParser::JSONPPathEntry> JSONPPath;
     803            Vector<JSONPPathEntry> JSONPPath;
    789804            JSONPPath.swap(JSONPData[entry].m_path);
    790805            JSValue JSONPValue = JSONPData[entry].m_value.get();
    791             if (JSONPPath.size() == 1 && JSONPPath[0].m_type == LiteralParser::JSONPPathEntryTypeDeclare) {
     806            if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
    792807                if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
    793808                    PutPropertySlot slot;
     
    801816            JSValue baseObject(globalObject);
    802817            for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
    803                 ASSERT(JSONPPath[i].m_type != LiteralParser::JSONPPathEntryTypeDeclare);
     818                ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
    804819                switch (JSONPPath[i].m_type) {
    805                 case LiteralParser::JSONPPathEntryTypeDot: {
     820                case JSONPPathEntryTypeDot: {
    806821                    if (i == 0) {
    807822                        PropertySlot slot(globalObject);
     
    818833                    continue;
    819834                }
    820                 case LiteralParser::JSONPPathEntryTypeLookup: {
     835                case JSONPPathEntryTypeLookup: {
    821836                    baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
    822837                    if (callFrame->hadException())
     
    831846            PutPropertySlot slot;
    832847            switch (JSONPPath.last().m_type) {
    833             case LiteralParser::JSONPPathEntryTypeCall: {
     848            case JSONPPathEntryTypeCall: {
    834849                JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
    835850                if (callFrame->hadException())
     
    847862                break;
    848863            }
    849             case LiteralParser::JSONPPathEntryTypeDot: {
     864            case JSONPPathEntryTypeDot: {
    850865                baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
    851866                if (callFrame->hadException())
     
    853868                break;
    854869            }
    855             case LiteralParser::JSONPPathEntryTypeLookup: {
     870            case JSONPPathEntryTypeLookup: {
    856871                baseObject.put(callFrame, JSONPPath.last().m_pathIndex, JSONPValue);
    857872                if (callFrame->hadException())
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

    r99436 r99812  
    446446    UString s = x.toString(exec);
    447447
    448     LiteralParser preparser(exec, s.characters(), s.length(), LiteralParser::NonStrictJSON);
    449     if (JSValue parsedObject = preparser.tryLiteralParse())
    450         return JSValue::encode(parsedObject);
     448    if (s.is8Bit()) {
     449        LiteralParser<LChar> preparser(exec, s.characters8(), s.length(), NonStrictJSON);
     450        if (JSValue parsedObject = preparser.tryLiteralParse())
     451            return JSValue::encode(parsedObject);
     452    } else {
     453        LiteralParser<UChar> preparser(exec, s.characters16(), s.length(), NonStrictJSON);
     454        if (JSValue parsedObject = preparser.tryLiteralParse())
     455            return JSValue::encode(parsedObject);       
     456    }
    451457
    452458    EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false);
  • trunk/Source/JavaScriptCore/runtime/JSONObject.cpp

    r99754 r99812  
    820820        return JSValue::encode(jsNull());
    821821
     822    JSValue unfiltered;
    822823    LocalScope scope(exec->globalData());
    823     LiteralParser jsonParser(exec, source.characters(), source.length(), LiteralParser::StrictJSON);
    824     JSValue unfiltered = jsonParser.tryLiteralParse();
    825     if (!unfiltered)
    826         return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage()));
     824    if (source.is8Bit()) {
     825        LiteralParser<LChar> jsonParser(exec, source.characters8(), source.length(), StrictJSON);
     826        unfiltered = jsonParser.tryLiteralParse();
     827        if (!unfiltered)
     828            return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage()));
     829    } else {
     830        LiteralParser<UChar> jsonParser(exec, source.characters16(), source.length(), StrictJSON);
     831        unfiltered = jsonParser.tryLiteralParse();
     832        if (!unfiltered)
     833            return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage()));       
     834    }
    827835   
    828836    if (exec->argumentCount() < 2)
  • trunk/Source/JavaScriptCore/runtime/LiteralParser.cpp

    r99436 r99812  
    3737namespace JSC {
    3838
    39 static inline bool isJSONWhiteSpace(const UChar& c)
     39template <typename CharType>
     40static inline bool isJSONWhiteSpace(const CharType& c)
    4041{
    4142    // The JSON RFC 4627 defines a list of allowed characters to be considered
     
    4445}
    4546
    46 bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo)
     47template <typename CharType>
     48bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo)
    4749{
    4850    if (m_lexer.next() != TokIdentifier)
     
    121123}
    122124   
    123 ALWAYS_INLINE const Identifier LiteralParser::makeIdentifier(const UChar* characters, size_t length)
     125template <typename CharType>
     126ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const LChar* characters, size_t length)
    124127{
    125128    if (!length)
     
    140143}
    141144
    142 template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
     145template <typename CharType>
     146ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const UChar* characters, size_t length)
     147{
     148    if (!length)
     149        return m_exec->globalData().propertyNames->emptyIdentifier;
     150    if (characters[0] >= MaximumCachableCharacter)
     151        return Identifier(&m_exec->globalData(), characters, length);
     152
     153    if (length == 1) {
     154        if (!m_shortIdentifiers[characters[0]].isNull())
     155            return m_shortIdentifiers[characters[0]];
     156        m_shortIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
     157        return m_shortIdentifiers[characters[0]];
     158    }
     159    if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
     160        return m_recentIdentifiers[characters[0]];
     161    m_recentIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
     162    return m_recentIdentifiers[characters[0]];
     163}
     164
     165template <typename CharType>
     166template <ParserMode mode> TokenType LiteralParser<CharType>::Lexer::lex(LiteralParserToken<CharType>& token)
    143167{
    144168    while (m_ptr < m_end && isJSONWhiteSpace(*m_ptr))
     
    241265            return TokAssign;
    242266        }
    243         if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$') {
    244             while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
    245                 m_ptr++;
    246             token.stringToken = token.start;
    247             token.stringLength = m_ptr - token.start;
    248             token.type = TokIdentifier;
    249             token.end = m_ptr;
    250             return TokIdentifier;
    251         }
     267        if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$')
     268            return lexIdentifier(token);
    252269        if (*m_ptr == '\'') {
    253270            if (mode == StrictJSON) {
     
    262279}
    263280
    264 LiteralParser::TokenType LiteralParser::Lexer::next()
     281template <>
     282ALWAYS_INLINE TokenType LiteralParser<LChar>::Lexer::lexIdentifier(LiteralParserToken<LChar>& token)
     283{
     284    while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
     285        m_ptr++;
     286    token.stringIs8Bit = 1;
     287    token.stringToken8 = token.start;
     288    token.stringLength = m_ptr - token.start;
     289    token.type = TokIdentifier;
     290    token.end = m_ptr;
     291    return TokIdentifier;
     292}
     293
     294template <>
     295ALWAYS_INLINE TokenType LiteralParser<UChar>::Lexer::lexIdentifier(LiteralParserToken<UChar>& token)
     296{
     297    while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
     298        m_ptr++;
     299    token.stringIs8Bit = 0;
     300    token.stringToken16 = token.start;
     301    token.stringLength = m_ptr - token.start;
     302    token.type = TokIdentifier;
     303    token.end = m_ptr;
     304    return TokIdentifier;
     305}
     306
     307template <typename CharType>
     308TokenType LiteralParser<CharType>::Lexer::next()
    265309{
    266310    if (m_mode == NonStrictJSON)
     
    271315}
    272316
    273 template <LiteralParser::ParserMode mode, UChar terminator> static inline bool isSafeStringCharacter(UChar c)
    274 {
    275     return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || c == '\t';
     317template <>
     318ALWAYS_INLINE void setParserTokenString<LChar>(LiteralParserToken<LChar>& token, const LChar* string)
     319{
     320    token.stringIs8Bit = 1;
     321    token.stringToken8 = string;
     322}
     323
     324template <>
     325ALWAYS_INLINE void setParserTokenString<UChar>(LiteralParserToken<UChar>& token, const UChar* string)
     326{
     327    token.stringIs8Bit = 0;
     328    token.stringToken16 = string;
     329}
     330
     331template <ParserMode mode, typename CharType, LChar terminator> static inline bool isSafeStringCharacter(LChar c)
     332{
     333    return (c >= ' ' && c != '\\' && c != terminator) || c == '\t';
     334}
     335
     336template <ParserMode mode, typename CharType, UChar terminator> static inline bool isSafeStringCharacter(UChar c)
     337{
     338    return (c >= ' ' && (mode == StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || c == '\t';
    276339}
    277340
    278341// "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions.
    279 template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
     342template <typename CharType>
     343template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParser<CharType>::Lexer::lexString(LiteralParserToken<CharType>& token)
    280344{
    281345    ++m_ptr;
    282     const UChar* runStart = m_ptr;
     346    const CharType* runStart = m_ptr;
    283347    UStringBuilder builder;
    284348    do {
    285349        runStart = m_ptr;
    286         while (m_ptr < m_end && isSafeStringCharacter<mode, terminator>(*m_ptr))
     350        while (m_ptr < m_end && isSafeStringCharacter<mode, CharType, terminator>(*m_ptr))
    287351            ++m_ptr;
    288352        if (builder.length())
     
    341405                        }
    342406                    }
    343                     builder.append(JSC::Lexer<UChar>::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
     407                    builder.append(JSC::Lexer<CharType>::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
    344408                    m_ptr += 5;
    345409                    break;
     
    364428    if (builder.isEmpty()) {
    365429        token.stringBuffer = UString();
    366         token.stringToken = runStart;
     430        setParserTokenString<CharType>(token, runStart);
    367431        token.stringLength = m_ptr - runStart;
    368432    } else {
    369433        token.stringBuffer = builder.toUString();
    370         token.stringToken = token.stringBuffer.characters();
     434        if (token.stringBuffer.is8Bit()) {
     435            token.stringIs8Bit = 1;
     436            token.stringToken8 = token.stringBuffer.characters8();
     437        } else {
     438            token.stringIs8Bit = 0;
     439            token.stringToken16 = token.stringBuffer.characters16();
     440        }
    371441        token.stringLength = token.stringBuffer.length();
    372442    }
     
    376446}
    377447
    378 LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& token)
     448template <typename CharType>
     449TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>& token)
    379450{
    380451    // ES5 and json.org define numbers as
     
    424495        token.type = TokNumber;
    425496        token.end = m_ptr;
    426         const UChar* digit = token.start;
     497        const CharType* digit = token.start;
    427498        int negative = 1;
    428499        if (*digit == '-') {
     
    472543}
    473544
    474 JSValue LiteralParser::parse(ParserState initialState)
     545template <typename CharType>
     546JSValue LiteralParser<CharType>::parse(ParserState initialState)
    475547{
    476548    ParserState state = initialState;
     
    527599                TokenType type = m_lexer.next();
    528600                if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) {
    529                     Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
     601                    LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
    530602
    531603                    // Check for colon
     
    536608                   
    537609                    m_lexer.next();
    538                     identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
     610                    if (identifierToken.stringIs8Bit)
     611                        identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength));
     612                    else
     613                        identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength));
    539614                    stateStack.append(DoParseObjectEndExpression);
    540615                    goto startParseExpression;
     
    556631                    return JSValue();
    557632                }
    558                 Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
     633                LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
    559634
    560635                // Check for colon
     
    565640
    566641                m_lexer.next();
    567                 identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
     642                if (identifierToken.stringIs8Bit)
     643                    identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength));
     644                else
     645                    identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength));
    568646                stateStack.append(DoParseObjectEndExpression);
    569647                goto startParseExpression;
     
    592670                        goto startParseObject;
    593671                    case TokString: {
    594                         Lexer::LiteralParserToken stringToken = m_lexer.currentToken();
     672                        LiteralParserToken<CharType> stringToken = m_lexer.currentToken();
    595673                        m_lexer.next();
    596                         lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken, stringToken.stringLength).ustring());
     674                        if (stringToken.stringIs8Bit)
     675                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).ustring());
     676                        else
     677                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).ustring());
    597678                        break;
    598679                    }
    599680                    case TokNumber: {
    600                         Lexer::LiteralParserToken numberToken = m_lexer.currentToken();
     681                        LiteralParserToken<CharType> numberToken = m_lexer.currentToken();
    601682                        m_lexer.next();
    602683                        lastValue = jsNumber(numberToken.numberToken);
     
    623704                        m_parseErrorMessage = "Unexpected token '}'";
    624705                        return JSValue();
    625                     case TokIdentifier:
    626                         m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken, m_lexer.currentToken().stringLength).ascii().data()).impl();
    627                         return JSValue();
     706                    case TokIdentifier: {
     707                        const LiteralParserToken<CharType>& token = m_lexer.currentToken();
     708                        if (token.stringIs8Bit)
     709                            m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data()).impl();
     710                        else
     711                            m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data()).impl();
     712                        return JSValue();
     713                    }
    628714                    case TokColon:
    629715                        m_parseErrorMessage = "Unexpected token ':'";
     
    738824}
    739825
    740 }
     826// Instantiate the two flavors of LiteralParser we need instead of putting most of this file in LiteralParser.h
     827template class LiteralParser<LChar>;
     828template class LiteralParser<UChar>;
     829
     830}
  • trunk/Source/JavaScriptCore/runtime/LiteralParser.h

    r95901 r99812  
    3434namespace JSC {
    3535
    36     class LiteralParser {
     36typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode;
     37
     38enum JSONPPathEntryType {
     39    JSONPPathEntryTypeDeclare, // var pathEntryName = JSON
     40    JSONPPathEntryTypeDot, // <prior entries>.pathEntryName = JSON
     41    JSONPPathEntryTypeLookup, // <prior entries>[pathIndex] = JSON
     42    JSONPPathEntryTypeCall // <prior entries>(JSON)
     43};
     44
     45enum ParserState { StartParseObject, StartParseArray, StartParseExpression,
     46                   StartParseStatement, StartParseStatementEndStatement,
     47                   DoParseObjectStartExpression, DoParseObjectEndExpression,
     48                   DoParseArrayStartExpression, DoParseArrayEndExpression };
     49enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace,
     50                 TokString, TokIdentifier, TokNumber, TokColon,
     51                 TokLParen, TokRParen, TokComma, TokTrue, TokFalse,
     52                 TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError };
     53   
     54struct JSONPPathEntry {
     55    JSONPPathEntryType m_type;
     56    Identifier m_pathEntryName;
     57    int m_pathIndex;
     58};
     59
     60struct JSONPData {
     61    Vector<JSONPPathEntry> m_path;
     62    Strong<Unknown> m_value;
     63};
     64
     65template <typename CharType>
     66struct LiteralParserToken {
     67    TokenType type;
     68    const CharType* start;
     69    const CharType* end;
     70    UString stringBuffer;
     71    union {
     72        double numberToken;
     73        struct {
     74            union {
     75                const LChar* stringToken8;
     76                const UChar* stringToken16;
     77            };
     78            unsigned stringIs8Bit : 1;
     79            unsigned stringLength : 31;
     80        };
     81    };
     82};
     83
     84template <typename CharType>
     85ALWAYS_INLINE void setParserTokenString(LiteralParserToken<CharType>&, const CharType* string);
     86
     87template <typename CharType>
     88class LiteralParser {
     89public:
     90    LiteralParser(ExecState* exec, const CharType* characters, unsigned length, ParserMode mode)
     91        : m_exec(exec)
     92        , m_lexer(characters, length, mode)
     93        , m_mode(mode)
     94    {
     95    }
     96   
     97    UString getErrorMessage()
     98    {
     99        if (!m_lexer.getErrorMessage().isEmpty())
     100            return String::format("JSON Parse error: %s", m_lexer.getErrorMessage().ascii().data()).impl();
     101        if (!m_parseErrorMessage.isEmpty())
     102            return String::format("JSON Parse error: %s", m_parseErrorMessage.ascii().data()).impl();
     103        return "JSON Parse error: Unable to parse JSON string";
     104    }
     105   
     106    JSValue tryLiteralParse()
     107    {
     108        m_lexer.next();
     109        JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement);
     110        if (m_lexer.currentToken().type == TokSemi)
     111            m_lexer.next();
     112        if (m_lexer.currentToken().type != TokEnd)
     113            return JSValue();
     114        return result;
     115    }
     116   
     117    bool tryJSONPParse(Vector<JSONPData>&, bool needsFullSourceInfo);
     118
     119private:
     120    class Lexer {
    37121    public:
    38         typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode;
    39         LiteralParser(ExecState* exec, const UChar* characters, unsigned length, ParserMode mode)
    40             : m_exec(exec)
    41             , m_lexer(characters, length, mode)
    42             , m_mode(mode)
     122        Lexer(const CharType* characters, unsigned length, ParserMode mode)
     123            : m_mode(mode)
     124            , m_ptr(characters)
     125            , m_end(characters + length)
    43126        {
    44127        }
    45128       
    46         UString getErrorMessage()
    47         {
    48             if (!m_lexer.getErrorMessage().isEmpty())
    49                 return String::format("JSON Parse error: %s", m_lexer.getErrorMessage().ascii().data()).impl();
    50             if (!m_parseErrorMessage.isEmpty())
    51                 return String::format("JSON Parse error: %s", m_parseErrorMessage.ascii().data()).impl();
    52             return "JSON Parse error: Unable to parse JSON string";
     129        TokenType next();
     130       
     131        const LiteralParserToken<CharType>& currentToken()
     132        {
     133            return m_currentToken;
    53134        }
    54135       
    55         JSValue tryLiteralParse()
    56         {
    57             m_lexer.next();
    58             JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement);
    59             if (m_lexer.currentToken().type == TokSemi)
    60                 m_lexer.next();
    61             if (m_lexer.currentToken().type != TokEnd)
    62                 return JSValue();
    63             return result;
    64         }
     136        UString getErrorMessage() { return m_lexErrorMessage; }
    65137       
    66         enum JSONPPathEntryType {
    67             JSONPPathEntryTypeDeclare, // var pathEntryName = JSON
    68             JSONPPathEntryTypeDot, // <prior entries>.pathEntryName = JSON
    69             JSONPPathEntryTypeLookup, // <prior entries>[pathIndex] = JSON
    70             JSONPPathEntryTypeCall // <prior entries>(JSON)
    71         };
     138    private:
     139        UString m_lexErrorMessage;
     140        template <ParserMode mode> TokenType lex(LiteralParserToken<CharType>&);
     141        ALWAYS_INLINE TokenType lexIdentifier(LiteralParserToken<CharType>&);
     142        template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken<CharType>&);
     143        ALWAYS_INLINE TokenType lexNumber(LiteralParserToken<CharType>&);
     144        LiteralParserToken<CharType> m_currentToken;
     145        UString m_string;
     146        ParserMode m_mode;
     147        const CharType* m_ptr;
     148        const CharType* m_end;
     149    };
     150   
     151    class StackGuard;
     152    JSValue parse(ParserState);
    72153
    73         struct JSONPPathEntry {
    74             JSONPPathEntryType m_type;
    75             Identifier m_pathEntryName;
    76             int m_pathIndex;
    77         };
    78 
    79         struct JSONPData {
    80             Vector<JSONPPathEntry> m_path;
    81             Strong<Unknown> m_value;
    82         };
    83 
    84         bool tryJSONPParse(Vector<JSONPData>&, bool needsFullSourceInfo);
    85 
    86     private:
    87         enum ParserState { StartParseObject, StartParseArray, StartParseExpression,
    88                            StartParseStatement, StartParseStatementEndStatement,
    89                            DoParseObjectStartExpression, DoParseObjectEndExpression,
    90                            DoParseArrayStartExpression, DoParseArrayEndExpression };
    91         enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace,
    92                          TokString, TokIdentifier, TokNumber, TokColon,
    93                          TokLParen, TokRParen, TokComma, TokTrue, TokFalse,
    94                          TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError };
    95        
    96         class Lexer {
    97         public:
    98             struct LiteralParserToken {
    99                 TokenType type;
    100                 const UChar* start;
    101                 const UChar* end;
    102                 UString stringBuffer;
    103                 union {
    104                     double numberToken;
    105                     struct {
    106                         const UChar* stringToken;
    107                         int stringLength;
    108                     };
    109                 };
    110             };
    111             Lexer(const UChar* characters, unsigned length, ParserMode mode)
    112                 : m_mode(mode)
    113                 , m_ptr(characters)
    114                 , m_end(characters + length)
    115             {
    116             }
    117            
    118             TokenType next();
    119            
    120             const LiteralParserToken& currentToken()
    121             {
    122                 return m_currentToken;
    123             }
    124            
    125             UString getErrorMessage() { return m_lexErrorMessage; }
    126            
    127         private:
    128             UString m_lexErrorMessage;
    129             template <ParserMode mode> TokenType lex(LiteralParserToken&);
    130             template <ParserMode mode, UChar terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken&);
    131             ALWAYS_INLINE TokenType lexNumber(LiteralParserToken&);
    132             LiteralParserToken m_currentToken;
    133             UString m_string;
    134             ParserMode m_mode;
    135             const UChar* m_ptr;
    136             const UChar* m_end;
    137         };
    138        
    139         class StackGuard;
    140         JSValue parse(ParserState);
    141 
    142         ExecState* m_exec;
    143         LiteralParser::Lexer m_lexer;
    144         ParserMode m_mode;
    145         UString m_parseErrorMessage;
    146         static unsigned const MaximumCachableCharacter = 128;
    147         FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers;
    148         FixedArray<Identifier, MaximumCachableCharacter> m_recentIdentifiers;
    149         ALWAYS_INLINE const Identifier makeIdentifier(const UChar* characters, size_t length);
     154    ExecState* m_exec;
     155    typename LiteralParser<CharType>::Lexer m_lexer;
     156    ParserMode m_mode;
     157    UString m_parseErrorMessage;
     158    static unsigned const MaximumCachableCharacter = 128;
     159    FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers;
     160    FixedArray<Identifier, MaximumCachableCharacter> m_recentIdentifiers;
     161    ALWAYS_INLINE const Identifier makeIdentifier(const LChar* characters, size_t length);
     162    ALWAYS_INLINE const Identifier makeIdentifier(const UChar* characters, size_t length);
    150163    };
    151164
  • trunk/Source/JavaScriptCore/runtime/UString.h

    r98643 r99812  
    9494        return m_impl->characters16();
    9595    }
     96
     97    template <typename CharType>
     98    inline const CharType* getCharacters() const;
    9699
    97100    bool is8Bit() const { return m_impl->is8Bit(); }
     
    135138    RefPtr<StringImpl> m_impl;
    136139};
     140
     141template<>
     142inline const LChar* UString::getCharacters<LChar>() const
     143{
     144    ASSERT(is8Bit());
     145    return characters8();
     146}
     147
     148template<>
     149inline const UChar* UString::getCharacters<UChar>() const
     150{
     151    ASSERT(!is8Bit());
     152    return characters16();
     153}
    137154
    138155NEVER_INLINE bool equalSlowCase(const UString& s1, const UString& s2);
  • trunk/Source/JavaScriptCore/wtf/text/StringBuilder.cpp

    r97371 r99812  
    159159}
    160160
    161 void StringBuilder::append(const char* characters, unsigned length)
     161void StringBuilder::append(const LChar* characters, unsigned length)
    162162{
    163163    if (!length)
     
    166166
    167167    UChar* dest = appendUninitialized(length);
    168     const char* end = characters + length;
     168    const LChar* end = characters + length;
    169169    while (characters < end)
    170         *(dest++) = *(const unsigned char*)(characters++);
     170        *(dest++) = *(characters++);
    171171}
    172172
  • trunk/Source/JavaScriptCore/wtf/text/StringBuilder.h

    r97371 r99812  
    4040
    4141    void append(const UChar*, unsigned);
    42     void append(const char*, unsigned);
     42    void append(const LChar*, unsigned);
     43
     44    ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast<const LChar*>(characters), length); }
    4345
    4446    void append(const String& string)
Note: See TracChangeset for help on using the changeset viewer.