Ignore:
Timestamp:
Jun 17, 2011, 9:25:57 PM (14 years ago)
Author:
[email protected]
Message:

2011-06-17 Oliver Hunt <[email protected]>

Reviewed by Gavin Barraclough.

JSONP is unnecessarily slow
https://bugs.webkit.org/show_bug.cgi?id=62920

JSONP has unfortunately become a fairly common idiom online, yet
it triggers very poor performance in JSC as we end up doing codegen
for a large number of property accesses that will

  • only be run once, so the vast amount of logic we dump to handle caching of accesses is unnecessary.
  • We are doing codegen that is directly proportional to just creating the object in the first place.

This patch extends the use of the literal parser to JSONP-like structures
in global code, handling a number of different forms I have seen online.
In an extreme case this improves performance of JSONP by more than 2x
due to removal of code generation and execution time, and a few optimisations
that I made to the parser itself.

  • API/JSValueRef.cpp: (JSValueMakeFromJSONString):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::callEval): (JSC::Interpreter::execute):
  • parser/Lexer.cpp: (JSC::Lexer::isKeyword):
  • parser/Lexer.h:
  • runtime/JSGlobalObjectFunctions.cpp: (JSC::globalFuncEval):
  • runtime/JSONObject.cpp: (JSC::JSONProtoFuncParse):
  • runtime/LiteralParser.cpp: (JSC::LiteralParser::tryJSONPParse): (JSC::LiteralParser::makeIdentifier): (JSC::LiteralParser::Lexer::lex): (JSC::LiteralParser::Lexer::next): (JSC::isSafeStringCharacter): (JSC::LiteralParser::Lexer::lexString): (JSC::LiteralParser::Lexer::lexNumber): (JSC::LiteralParser::parse):
  • runtime/LiteralParser.h: (JSC::LiteralParser::LiteralParser): (JSC::LiteralParser::tryLiteralParse): (JSC::LiteralParser::Lexer::Lexer):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/LiteralParser.h

    r65177 r89184  
    2727#define LiteralParser_h
    2828
     29#include "Identifier.h"
    2930#include "JSGlobalObjectFunctions.h"
    3031#include "JSValue.h"
     
    3536    class LiteralParser {
    3637    public:
    37         typedef enum { StrictJSON, NonStrictJSON } ParserMode;
    38         LiteralParser(ExecState* exec, const UString& s, ParserMode mode)
     38        typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode;
     39        LiteralParser(ExecState* exec, const UChar* characters, unsigned length, ParserMode mode)
    3940            : m_exec(exec)
    40             , m_lexer(s, mode)
     41            , m_lexer(characters, length, mode)
    4142            , m_mode(mode)
    4243        {
     
    4748            m_lexer.next();
    4849            JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement);
     50            if (m_lexer.currentToken().type == TokSemi)
     51                m_lexer.next();
    4952            if (m_lexer.currentToken().type != TokEnd)
    5053                return JSValue();
    5154            return result;
    5255        }
     56       
     57        enum JSONPPathEntryType {
     58            JSONPPathEntryTypeDeclare, // var pathEntryName = JSON
     59            JSONPPathEntryTypeDot, // <prior entries>.pathEntryName = JSON
     60            JSONPPathEntryTypeLookup // <prior entries>[pathIndex] = JSON
     61        };
     62
     63        struct JSONPPathEntry {
     64            JSONPPathEntryType m_type;
     65            Identifier m_pathEntryName;
     66            int m_pathIndex;
     67        };
     68
     69        struct JSONPData {
     70            Vector<JSONPPathEntry> m_path;
     71            Strong<Unknown> m_value;
     72        };
     73
     74        bool tryJSONPParse(Vector<JSONPData>&);
     75
    5376    private:
    5477        enum ParserState { StartParseObject, StartParseArray, StartParseExpression,
     
    5982                         TokString, TokIdentifier, TokNumber, TokColon,
    6083                         TokLParen, TokRParen, TokComma, TokTrue, TokFalse,
    61                          TokNull, TokEnd, TokError };
    62 
     84                         TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError };
     85       
    6386        class Lexer {
    6487        public:
     
    6790                const UChar* start;
    6891                const UChar* end;
    69                 UString stringToken;
    70                 double numberToken;
     92                UString stringBuffer;
     93                union {
     94                    double numberToken;
     95                    struct {
     96                        const UChar* stringToken;
     97                        int stringLength;
     98                    };
     99                };
    71100            };
    72             Lexer(const UString& s, ParserMode mode)
    73                 : m_string(s)
    74                 , m_mode(mode)
    75                 , m_ptr(s.characters())
    76                 , m_end(s.characters() + s.length())
     101            Lexer(const UChar* characters, unsigned length, ParserMode mode)
     102                : m_mode(mode)
     103                , m_ptr(characters)
     104                , m_end(characters + length)
    77105            {
    78106            }
    79107           
    80             TokenType next()
    81             {
    82                 return lex(m_currentToken);
    83             }
     108            TokenType next();
    84109           
    85110            const LiteralParserToken& currentToken()
     
    89114           
    90115        private:
    91             TokenType lex(LiteralParserToken&);
    92             template <ParserMode mode> TokenType lexString(LiteralParserToken&);
    93             TokenType lexNumber(LiteralParserToken&);
     116            template <ParserMode mode> TokenType lex(LiteralParserToken&);
     117            template <ParserMode mode, UChar terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken&);
     118            ALWAYS_INLINE TokenType lexNumber(LiteralParserToken&);
    94119            LiteralParserToken m_currentToken;
    95120            UString m_string;
     
    105130        LiteralParser::Lexer m_lexer;
    106131        ParserMode m_mode;
     132        static unsigned const MaximumCachableCharacter = 128;
     133        FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers;
     134        FixedArray<Identifier, MaximumCachableCharacter> m_recentIdentifiers;
     135        ALWAYS_INLINE const Identifier makeIdentifier(const UChar* characters, size_t length);
    107136    };
     137
    108138}
    109139
Note: See TracChangeset for help on using the changeset viewer.