Changeset 28854 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Dec 18, 2007, 11:42:29 PM (17 years ago)
Author:
[email protected]
Message:

Replace post-parse pass to find declarations with logic in the parser itself

Reviewed by Geoff.

Instead of finding declarations in a pass following the initial parsing of
a program, we incorporate the logic directly into the parser. This lays
the groundwork for further optimisations (such as improving performance in
declaration expressions -- var x = y; -- to match that of standard assignment)
in addition to providing a 0.4% performance improvement in SunSpider.

Location:
trunk/JavaScriptCore/kjs
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/Parser.cpp

    r28604 r28854  
    6161    lexer.clear();
    6262
    63     Node::clearNewNodes();
     63    ParserRefCounted::deleteNewObjects();
    6464
    6565    if (parseError || lexError) {
  • trunk/JavaScriptCore/kjs/Parser.h

    r28604 r28854  
    2929#include <wtf/Noncopyable.h>
    3030#include <wtf/OwnPtr.h>
     31#include <wtf/RefPtr.h>
    3132#include "nodes.h"
    3233
     
    3839
    3940    struct UChar;
     41
     42    template <typename T> struct ParserRefCountedData : ParserRefCounted {
     43        T data;
     44    };
    4045
    4146    class Parser : Noncopyable {
     
    4954        int sourceId() const { return m_sourceId; }
    5055
    51         void didFinishParsing(SourceElements* sourceElements, int lastLine)
     56        void didFinishParsing(SourceElements* sourceElements, ParserRefCountedData<DeclarationStacks::VarStack>* varStack,
     57                              ParserRefCountedData<DeclarationStacks::FunctionStack>* funcStack, int lastLine)
    5258        {
    5359            m_sourceElements.set(sourceElements);
     60            m_varDeclarations = varStack;
     61            m_funcDeclarations = funcStack;
    5462            m_lastLine = lastLine;
    5563        }
     
    6573        int m_sourceId;
    6674        OwnPtr<SourceElements> m_sourceElements;
     75        RefPtr<ParserRefCountedData<DeclarationStacks::VarStack> > m_varDeclarations;
     76        RefPtr<ParserRefCountedData<DeclarationStacks::FunctionStack> > m_funcDeclarations;
    6777        int m_lastLine;
    6878    };
     
    8191            return 0;
    8292        }
    83         RefPtr<ParsedNode> node = new ParsedNode(m_sourceElements.release());
     93        RefPtr<ParsedNode> node = new ParsedNode(m_sourceElements.release(),
     94                                                 m_varDeclarations ? &m_varDeclarations->data : 0,
     95                                                 m_funcDeclarations ? &m_funcDeclarations->data : 0);
     96        m_varDeclarations = 0;
     97        m_funcDeclarations = 0;
    8498        m_sourceURL = UString();
    8599        node->setLoc(startingLineNumber, m_lastLine);
  • trunk/JavaScriptCore/kjs/grammar.y

    r28581 r28854  
    8585#endif
    8686
     87template <typename T> struct NodeInfo {
     88    T m_node;
     89    ParserRefCountedData<DeclarationStacks::VarStack>* m_varDeclarations;
     90    ParserRefCountedData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
     91};
     92
     93template <typename T> NodeInfo<T> createNodeInfo(T node, ParserRefCountedData<DeclarationStacks::VarStack>* varDecls,
     94                                                 ParserRefCountedData<DeclarationStacks::FunctionStack>* funcDecls)
     95{
     96    NodeInfo<T> result = {node, varDecls, funcDecls};
     97    return result;
     98}
     99
     100template <typename T> T mergeDeclarationLists(T decls1, T decls2)
     101{
     102    // decls1 or both are null
     103    if (!decls1)
     104        return decls2;
     105    // only decls1 is non-null
     106    if (!decls2)
     107        return decls1;
     108
     109    // Both are non-null
     110    decls1->data.append(decls2->data);
     111   
     112    // We manually release the declaration lists to avoid accumulating many many
     113    // unused heap allocated vectors
     114    decls2->ref();
     115    decls2->deref();
     116    return decls1;
     117}
     118
     119void appendToVarDeclarationList(ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, VarDeclNode* decl)
     120{
     121    if (!varDecls)
     122        varDecls = new ParserRefCountedData<DeclarationStacks::VarStack>;
     123    varDecls->data.append(decl);
     124}
     125
     126typedef NodeInfo<StatementNode*> StatementNodeInfo;
     127typedef NodeInfo<CaseBlockNode*> CaseBlockNodeInfo;
     128typedef NodeInfo<CaseClauseNode*> CaseClauseNodeInfo;
     129typedef NodeInfo<SourceElementsStub*> SourceElementsInfo;
     130typedef NodeInfo<ClauseList> ClauseListInfo;
     131typedef NodeInfo<VarDeclList> VarDeclListInfo;
    87132%}
    88133
     
    99144    ArgumentsNode*      argumentsNode;
    100145    VarDeclNode*        varDeclNode;
    101     CaseBlockNode*      caseBlockNode;
    102     CaseClauseNode*     caseClauseNode;
     146    CaseBlockNodeInfo   caseBlockNode;
     147    CaseClauseNodeInfo  caseClauseNode;
    103148    FuncExprNode*       funcExprNode;
    104149    AssignExprNode*     assignExprNode;
    105150
    106151    // statement nodes
    107     StatementNode*      statementNode;
     152    StatementNodeInfo   statementNode;
    108153    FunctionBodyNode*   functionBodyNode;
    109154    ProgramNode*        programNode;
    110155
    111     SourceElementsStub* sourceElements;
     156    SourceElementsInfo sourceElements;
    112157    PropertyList        propertyList;
    113158    ArgumentList        argumentList;
    114     VarDeclList         varDeclList;
    115     ClauseList          clauseList;
     159    VarDeclListInfo     varDeclList;
     160    ClauseListInfo      clauseList;
    116161    ElementList         elementList;
    117162    ParameterList       parameterList;
     
    663708
    664709Block:
    665     '{' '}'                             { $$ = new BlockNode(new SourceElements); DBG($$, @1, @2); }
    666   | '{' SourceElements '}'              { $$ = new BlockNode($2->release()); DBG($$, @1, @3); }
     710    '{' '}'                             { $$ = createNodeInfo<StatementNode*>(new BlockNode(new SourceElements), 0, 0);
     711                                          DBG($$.m_node, @1, @2); }
     712  | '{' SourceElements '}'              { $$ = createNodeInfo<StatementNode*>(new BlockNode($2.m_node->release()), $2.m_varDeclarations, $2.m_funcDeclarations);
     713                                          DBG($$.m_node, @1, @3); }
    667714;
    668715
    669716VariableStatement:
    670     VAR VariableDeclarationList ';'     { $$ = new VarStatementNode($2.head); DBG($$, @1, @3); }
    671   | VAR VariableDeclarationList error   { $$ = new VarStatementNode($2.head); DBG($$, @1, @2); AUTO_SEMICOLON; }
     717    VAR VariableDeclarationList ';'     { $$ = createNodeInfo<StatementNode*>(new VarStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);
     718                                          DBG($$.m_node, @1, @3); }
     719  | VAR VariableDeclarationList error   { $$ = createNodeInfo<StatementNode*>(new VarStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);
     720                                          DBG($$.m_node, @1, @2);
     721                                          AUTO_SEMICOLON; }
    672722;
    673723
    674724VariableDeclarationList:
    675     VariableDeclaration                 { $$.head = $1;
    676                                           $$.tail = $$.head; }
     725    VariableDeclaration                 { $$.m_node.head = $1;
     726                                          $$.m_node.tail = $$.m_node.head;
     727                                          $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
     728                                          $$.m_varDeclarations->data.append($1);
     729                                          $$.m_funcDeclarations = 0;
     730                                        }
    677731  | VariableDeclarationList ',' VariableDeclaration
    678                                         { $$.head = $1.head;
    679                                           $1.tail->next = $3;
    680                                           $$.tail = $3; }
     732                                        { $$.m_node.head = $1.m_node.head;
     733                                          $1.m_node.tail->next = $3;
     734                                          $$.m_node.tail = $3;
     735                                          $$.m_varDeclarations = $1.m_varDeclarations;
     736                                          $$.m_varDeclarations->data.append($3);
     737                                          $$.m_funcDeclarations = 0;
     738                                        }
    681739;
    682740
    683741VariableDeclarationListNoIn:
    684     VariableDeclarationNoIn             { $$.head = $1;
    685                                           $$.tail = $$.head; }
     742    VariableDeclarationNoIn             { $$.m_node.head = $1;
     743                                          $$.m_node.tail = $$.m_node.head;
     744                                          $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
     745                                          $$.m_varDeclarations->data.append($1);
     746                                          $$.m_funcDeclarations = 0; }
    686747  | VariableDeclarationListNoIn ',' VariableDeclarationNoIn
    687                                         { $$.head = $1.head;
    688                                           $1.tail->next = $3;
    689                                           $$.tail = $3; }
     748                                        { $$.m_node.head = $1.m_node.head;
     749                                          $1.m_node.tail->next = $3;
     750                                          $$.m_node.tail = $3;
     751                                          $$.m_varDeclarations = $1.m_varDeclarations;
     752                                          $$.m_varDeclarations->data.append($3);
     753                                          $$.m_funcDeclarations = 0; }
    690754;
    691755
     
    701765
    702766ConstStatement:
    703     CONSTTOKEN ConstDeclarationList ';' { $$ = new VarStatementNode($2.head); DBG($$, @1, @3); }
     767    CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeInfo<StatementNode*>(new VarStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);
     768                                          DBG($$.m_node, @1, @3); }
    704769  | CONSTTOKEN ConstDeclarationList error
    705                                         { $$ = new VarStatementNode($2.head); DBG($$, @1, @2); AUTO_SEMICOLON; }
     770                                        { $$ = createNodeInfo<StatementNode*>(new VarStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);
     771                                          DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
    706772;
    707773
    708774ConstDeclarationList:
    709     ConstDeclaration                    { $$.head = $1;
    710                                           $$.tail = $$.head; }
     775    ConstDeclaration                    { $$.m_node.head = $1;
     776                                          $$.m_node.tail = $$.m_node.head;
     777                                          $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
     778                                          $$.m_varDeclarations->data.append($1);
     779                                          $$.m_funcDeclarations = 0; }
    711780  | ConstDeclarationList ',' ConstDeclaration
    712                                         { $$.head = $1.head;
    713                                           $1.tail->next = $3;
    714                                           $$.tail = $3; }
     781                                        {  $$.m_node.head = $1.m_node.head;
     782                                          $1.m_node.tail->next = $3;
     783                                          $$.m_node.tail = $3;
     784                                          $$.m_varDeclarations = $1.m_varDeclarations;
     785                                          $$.m_varDeclarations->data.append($3);
     786                                          $$.m_funcDeclarations = 0; }
    715787;
    716788
     
    729801
    730802EmptyStatement:
    731     ';'                                 { $$ = new EmptyStatementNode(); }
     803    ';'                                 { $$ = createNodeInfo<StatementNode*>(new EmptyStatementNode(), 0, 0); }
    732804;
    733805
    734806ExprStatement:
    735     ExprNoBF ';'                        { $$ = new ExprStatementNode($1); DBG($$, @1, @2); }
    736   | ExprNoBF error                      { $$ = new ExprStatementNode($1); DBG($$, @1, @1); AUTO_SEMICOLON; }
     807    ExprNoBF ';'                        { $$ = createNodeInfo<StatementNode*>(new ExprStatementNode($1), 0, 0);
     808                                          DBG($$.m_node, @1, @2); }
     809  | ExprNoBF error                      { $$ = createNodeInfo<StatementNode*>(new ExprStatementNode($1), 0, 0);
     810                                          DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
    737811;
    738812
    739813IfStatement:
    740814    IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE
    741                                         { $$ = new IfNode($3, $5, 0); DBG($$, @1, @4); }
     815                                        { $$ = createNodeInfo<StatementNode*>(new IfNode($3, $5.m_node, 0), $5.m_varDeclarations, $5.m_funcDeclarations);
     816                                          DBG($$.m_node, @1, @4); }
    742817  | IF '(' Expr ')' Statement ELSE Statement
    743                                         { $$ = new IfNode($3, $5, $7); DBG($$, @1, @4); }
     818                                        { $$ = createNodeInfo<StatementNode*>(new IfNode($3, $5.m_node, $7.m_node), mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations));
     819                                          DBG($$.m_node, @1, @4); }
    744820;
    745821
    746822IterationStatement:
    747     DO Statement WHILE '(' Expr ')' ';'    { $$ = new DoWhileNode($2, $5); DBG($$, @1, @3); }
    748   | DO Statement WHILE '(' Expr ')' error  { $$ = new DoWhileNode($2, $5); DBG($$, @1, @3); } // Always performs automatic semicolon insertion.
    749   | WHILE '(' Expr ')' Statement        { $$ = new WhileNode($3, $5); DBG($$, @1, @4); }
     823    DO Statement WHILE '(' Expr ')' ';'    { $$ = createNodeInfo<StatementNode*>(new DoWhileNode($2.m_node, $5), $2.m_varDeclarations, $2.m_funcDeclarations);
     824                                             DBG($$.m_node, @1, @3); }
     825  | DO Statement WHILE '(' Expr ')' error  { $$ = createNodeInfo<StatementNode*>(new DoWhileNode($2.m_node, $5), $2.m_varDeclarations, $2.m_funcDeclarations);
     826                                             DBG($$.m_node, @1, @3); } // Always performs automatic semicolon insertion.
     827  | WHILE '(' Expr ')' Statement        { $$ = createNodeInfo<StatementNode*>(new WhileNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations);
     828                                          DBG($$.m_node, @1, @4); }
    750829  | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement
    751                                         { $$ = new ForNode($3, $5, $7, $9); DBG($$, @1, @8); }
     830                                        { $$ = createNodeInfo<StatementNode*>(new ForNode($3, $5, $7, $9.m_node), $9.m_varDeclarations, $9.m_funcDeclarations);
     831                                          DBG($$.m_node, @1, @8);
     832                                        }
    752833  | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
    753                                         { $$ = new ForNode($4.head, $6, $8, $10); DBG($$, @1, @9); }
     834                                        { $$ = createNodeInfo<StatementNode*>(new ForNode($4.m_node.head, $6, $8, $10.m_node),
     835                                                                              mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations),
     836                                                                              mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations));
     837                                          DBG($$.m_node, @1, @9); }
    754838  | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
    755839                                        {
     
    757841                                            if (!n->isLocation())
    758842                                                YYABORT;
    759                                             $$ = new ForInNode(n, $5, $7);
    760                                             DBG($$, @1, @6);
     843                                            $$ = createNodeInfo<StatementNode*>(new ForInNode(n, $5, $7.m_node), $7.m_varDeclarations, $7.m_funcDeclarations);
     844                                            DBG($$.m_node, @1, @6);
    761845                                        }
    762846  | FOR '(' VAR IDENT INTOKEN Expr ')' Statement
    763                                         { $$ = new ForInNode(*$4, 0, $6, $8); DBG($$, @1, @7); }
     847                                        { ForInNode *forIn = new ForInNode(*$4, 0, $6, $8.m_node);
     848                                          appendToVarDeclarationList($8.m_varDeclarations, forIn->getVarDecl());
     849                                          $$ = createNodeInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations);
     850                                          DBG($$.m_node, @1, @7); }
    764851  | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement
    765                                         { $$ = new ForInNode(*$4, $5, $7, $9); DBG($$, @1, @8); }
     852                                        { ForInNode *forIn = new ForInNode(*$4, $5, $7, $9.m_node);
     853                                          appendToVarDeclarationList($9.m_varDeclarations, forIn->getVarDecl());
     854                                          $$ = createNodeInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations);
     855                                          DBG($$.m_node, @1, @8); }
    766856;
    767857
     
    777867
    778868ContinueStatement:
    779     CONTINUE ';'                        { $$ = new ContinueNode(); DBG($$, @1, @2); }
    780   | CONTINUE error                      { $$ = new ContinueNode(); DBG($$, @1, @1); AUTO_SEMICOLON; }
    781   | CONTINUE IDENT ';'                  { $$ = new ContinueNode(*$2); DBG($$, @1, @3); }
    782   | CONTINUE IDENT error                { $$ = new ContinueNode(*$2); DBG($$, @1, @2); AUTO_SEMICOLON; }
     869    CONTINUE ';'                        { $$ = createNodeInfo<StatementNode*>(new ContinueNode(), 0, 0);
     870                                          DBG($$.m_node, @1, @2); }
     871  | CONTINUE error                      { $$ = createNodeInfo<StatementNode*>(new ContinueNode(), 0, 0);
     872                                          DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
     873  | CONTINUE IDENT ';'                  { $$ = createNodeInfo<StatementNode*>(new ContinueNode(*$2), 0, 0);
     874                                          DBG($$.m_node, @1, @3); }
     875  | CONTINUE IDENT error                { $$ = createNodeInfo<StatementNode*>(new ContinueNode(*$2), 0, 0);
     876                                          DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
    783877;
    784878
    785879BreakStatement:
    786     BREAK ';'                           { $$ = new BreakNode(); DBG($$, @1, @2); }
    787   | BREAK error                         { $$ = new BreakNode(); DBG($$, @1, @1); AUTO_SEMICOLON; }
    788   | BREAK IDENT ';'                     { $$ = new BreakNode(*$2); DBG($$, @1, @3); }
    789   | BREAK IDENT error                   { $$ = new BreakNode(*$2); DBG($$, @1, @2); AUTO_SEMICOLON; }
     880    BREAK ';'                           { $$ = createNodeInfo<StatementNode*>(new BreakNode(), 0, 0); DBG($$.m_node, @1, @2); }
     881  | BREAK error                         { $$ = createNodeInfo<StatementNode*>(new BreakNode(), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
     882  | BREAK IDENT ';'                     { $$ = createNodeInfo<StatementNode*>(new BreakNode(*$2), 0, 0); DBG($$.m_node, @1, @3); }
     883  | BREAK IDENT error                   { $$ = createNodeInfo<StatementNode*>(new BreakNode(*$2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
    790884;
    791885
    792886ReturnStatement:
    793     RETURN ';'                          { $$ = new ReturnNode(0); DBG($$, @1, @2); }
    794   | RETURN error                        { $$ = new ReturnNode(0); DBG($$, @1, @1); AUTO_SEMICOLON; }
    795   | RETURN Expr ';'                     { $$ = new ReturnNode($2); DBG($$, @1, @3); }
    796   | RETURN Expr error                   { $$ = new ReturnNode($2); DBG($$, @1, @2); AUTO_SEMICOLON; }
     887    RETURN ';'                          { $$ = createNodeInfo<StatementNode*>(new ReturnNode(0), 0, 0); DBG($$.m_node, @1, @2); }
     888  | RETURN error                        { $$ = createNodeInfo<StatementNode*>(new ReturnNode(0), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
     889  | RETURN Expr ';'                     { $$ = createNodeInfo<StatementNode*>(new ReturnNode($2), 0, 0); DBG($$.m_node, @1, @3); }
     890  | RETURN Expr error                   { $$ = createNodeInfo<StatementNode*>(new ReturnNode($2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
    797891;
    798892
    799893WithStatement:
    800     WITH '(' Expr ')' Statement         { $$ = new WithNode($3, $5); DBG($$, @1, @4); }
     894    WITH '(' Expr ')' Statement         { $$ = createNodeInfo<StatementNode*>(new WithNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations);
     895                                          DBG($$.m_node, @1, @4); }
    801896;
    802897
    803898SwitchStatement:
    804     SWITCH '(' Expr ')' CaseBlock       { $$ = new SwitchNode($3, $5); DBG($$, @1, @4); }
     899    SWITCH '(' Expr ')' CaseBlock       { $$ = createNodeInfo<StatementNode*>(new SwitchNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations);
     900                                          DBG($$.m_node, @1, @4); }
    805901;
    806902
    807903CaseBlock:
    808     '{' CaseClausesOpt '}'              { $$ = new CaseBlockNode($2.head, 0, 0); }
     904    '{' CaseClausesOpt '}'              { $$ = createNodeInfo<CaseBlockNode*>(new CaseBlockNode($2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations); }
    809905  | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
    810                                         { $$ = new CaseBlockNode($2.head, $3, $4.head); }
     906                                        { $$ = createNodeInfo<CaseBlockNode*>(new CaseBlockNode($2.m_node.head, $3.m_node, $4.m_node.head),
     907                                                                              mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations),
     908                                                                              mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations)); }
    811909;
    812910
    813911CaseClausesOpt:
    814     /* nothing */                       { $$.head = 0; $$.tail = 0; }
     912    /* nothing */                       { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; }
    815913  | CaseClauses
    816914;
    817915
    818916CaseClauses:
    819     CaseClause                          { $$.head = new ClauseListNode($1);
    820                                           $$.tail = $$.head; }
    821   | CaseClauses CaseClause              { $$.head = $1.head;
    822                                           $$.tail = new ClauseListNode($1.tail, $2); }
     917    CaseClause                          { $$.m_node.head = new ClauseListNode($1.m_node);
     918                                          $$.m_node.tail = $$.m_node.head;
     919                                          $$.m_varDeclarations = $1.m_varDeclarations;
     920                                          $$.m_funcDeclarations = $1.m_funcDeclarations; }
     921  | CaseClauses CaseClause              { $$.m_node.head = $1.m_node.head;
     922                                          $$.m_node.tail = new ClauseListNode($1.m_node.tail, $2.m_node);
     923                                          $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
     924                                          $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
     925                                        }
    823926;
    824927
    825928CaseClause:
    826     CASE Expr ':'                       { $$ = new CaseClauseNode($2); }
    827   | CASE Expr ':' SourceElements        { $$ = new CaseClauseNode($2, $4->release()); }
     929    CASE Expr ':'                       { $$ = createNodeInfo<CaseClauseNode*>(new CaseClauseNode($2), 0, 0); }
     930  | CASE Expr ':' SourceElements        { $$ = createNodeInfo<CaseClauseNode*>(new CaseClauseNode($2, $4.m_node->release()), $4.m_varDeclarations, $4.m_funcDeclarations); }
    828931;
    829932
    830933DefaultClause:
    831     DEFAULT ':'                         { $$ = new CaseClauseNode(0); }
    832   | DEFAULT ':' SourceElements          { $$ = new CaseClauseNode(0, $3->release()); }
     934    DEFAULT ':'                         { $$ = createNodeInfo<CaseClauseNode*>(new CaseClauseNode(0), 0, 0); }
     935  | DEFAULT ':' SourceElements          { $$ = createNodeInfo<CaseClauseNode*>(new CaseClauseNode(0, $3.m_node->release()), $3.m_varDeclarations, $3.m_funcDeclarations); }
    833936;
    834937
    835938LabelledStatement:
    836     IDENT ':' Statement                 { $3->pushLabel(*$1); $$ = new LabelNode(*$1, $3); }
     939    IDENT ':' Statement                 { $3.m_node->pushLabel(*$1);
     940                                          $$ = createNodeInfo<StatementNode*>(new LabelNode(*$1, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations); }
    837941;
    838942
    839943ThrowStatement:
    840     THROW Expr ';'                      { $$ = new ThrowNode($2); DBG($$, @1, @3); }
    841   | THROW Expr error                    { $$ = new ThrowNode($2); DBG($$, @1, @2); AUTO_SEMICOLON; }
     944    THROW Expr ';'                      { $$ = createNodeInfo<StatementNode*>(new ThrowNode($2), 0, 0); DBG($$.m_node, @1, @3); }
     945  | THROW Expr error                    { $$ = createNodeInfo<StatementNode*>(new ThrowNode($2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
    842946;
    843947
    844948TryStatement:
    845     TRY Block FINALLY Block             { $$ = new TryNode($2, CommonIdentifiers::shared()->nullIdentifier, 0, $4); DBG($$, @1, @2); }
    846   | TRY Block CATCH '(' IDENT ')' Block { $$ = new TryNode($2, *$5, $7, 0); DBG($$, @1, @2); }
     949    TRY Block FINALLY Block             { $$ = createNodeInfo<StatementNode*>(new TryNode($2.m_node, CommonIdentifiers::shared()->nullIdentifier, 0, $4.m_node),
     950                                                                              mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations),
     951                                                                              mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations));
     952                                          DBG($$.m_node, @1, @2); }
     953  | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeInfo<StatementNode*>(new TryNode($2.m_node, *$5, $7.m_node, 0),
     954                                                                              mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations),
     955                                                                              mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations));
     956                                          DBG($$.m_node, @1, @2); }
    847957  | TRY Block CATCH '(' IDENT ')' Block FINALLY Block
    848                                         { $$ = new TryNode($2, *$5, $7, $9); DBG($$, @1, @2); }
     958                                        { $$ = createNodeInfo<StatementNode*>(new TryNode($2.m_node, *$5, $7.m_node, $9.m_node),
     959                                                                              mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations),
     960                                                                              mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations));
     961                                          DBG($$.m_node, @1, @2); }
    849962;
    850963
    851964DebuggerStatement:
    852     DEBUGGER ';'                        { $$ = new EmptyStatementNode(); DBG($$, @1, @2); }
    853   | DEBUGGER error                      { $$ = new EmptyStatementNode(); DBG($$, @1, @1); AUTO_SEMICOLON; }
     965    DEBUGGER ';'                        { $$ = createNodeInfo<StatementNode*>(new EmptyStatementNode(), 0, 0);
     966                                          DBG($$.m_node, @1, @2); }
     967  | DEBUGGER error                      { $$ = createNodeInfo<StatementNode*>(new EmptyStatementNode(), 0, 0);
     968                                          DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
    854969;
    855970
     
    875990
    876991FunctionBody:
    877     /* not in spec */           { $$ = new FunctionBodyNode(new SourceElements); }
    878   | SourceElements              { $$ = new FunctionBodyNode($1->release()); }
     992    /* not in spec */           { $$ = new FunctionBodyNode(new SourceElements, 0, 0); }
     993  | SourceElements              { $$ = new FunctionBodyNode($1.m_node->release(), $1.m_varDeclarations ? &$1.m_varDeclarations->data : 0,
     994                                                                                  $1.m_funcDeclarations ? &$1.m_funcDeclarations->data : 0);
     995                                  // As in mergeDeclarationLists() we have to ref/deref to safely get rid of
     996                                  // the declaration lists.
     997                                  if ($1.m_varDeclarations) {
     998                                      $1.m_varDeclarations->ref();
     999                                      $1.m_varDeclarations->deref();
     1000                                  }
     1001                                  if ($1.m_funcDeclarations) {
     1002                                      $1.m_funcDeclarations->ref();
     1003                                      $1.m_funcDeclarations->deref();
     1004                                  }
     1005                                }
    8791006;
    8801007
    8811008Program:
    882     /* not in spec */                   { parser().didFinishParsing(new SourceElements, @0.last_line); }
    883     | SourceElements                    { parser().didFinishParsing($1->release(), @1.last_line); }
     1009    /* not in spec */                   { parser().didFinishParsing(new SourceElements, 0, 0, @0.last_line); }
     1010    | SourceElements                    { parser().didFinishParsing($1.m_node->release(), $1.m_varDeclarations, $1.m_funcDeclarations, @1.last_line); }
    8841011;
    8851012
    8861013SourceElements:
    887     SourceElement                       { $$ = new SourceElementsStub; $$->append($1); }
    888   | SourceElements SourceElement        { $$->append($2); }
     1014    SourceElement                       { $$.m_node = new SourceElementsStub;
     1015                                          $$.m_node->append($1.m_node);
     1016                                          $$.m_varDeclarations = $1.m_varDeclarations;
     1017                                          $$.m_funcDeclarations = $1.m_funcDeclarations;
     1018                                        }
     1019  | SourceElements SourceElement        { $$.m_node->append($2.m_node);
     1020                                          $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
     1021                                          $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
     1022                                        }
    8891023;
    8901024
    8911025SourceElement:
    892     FunctionDeclaration                 { $$ = $1; }
     1026    FunctionDeclaration                 { $$ = createNodeInfo<StatementNode*>($1, 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>); $$.m_funcDeclarations->data.append($1); }
    8931027  | Statement                           { $$ = $1; }
    8941028;
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r28608 r28854  
    111111static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };
    112112
    113 struct NodeCounter {
     113struct ParserRefCountedCounter {
    114114    static unsigned count;
    115     ~NodeCounter()
     115    ParserRefCountedCounter()
    116116    {
    117117        if (count)
     
    119119    }
    120120};
    121 unsigned NodeCounter::count = 0;
    122 static NodeCounter nodeCounter;
     121unsigned ParserRefCountedCounter::count = 0;
     122static ParserRefCountedCounter parserRefCountedCounter;
    123123#endif
    124124
    125 static HashSet<Node*>* newNodes;
    126 static HashCountedSet<Node*>* nodeExtraRefCounts;
     125static HashSet<ParserRefCounted*>* newTrackedObjects;
     126static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts;
     127
     128ParserRefCounted::ParserRefCounted()
     129{
     130#ifndef NDEBUG
     131    ++ParserRefCountedCounter::count;
     132#endif
     133  if (!newTrackedObjects)
     134      newTrackedObjects = new HashSet<ParserRefCounted*>;
     135  newTrackedObjects->add(this);
     136  ASSERT(newTrackedObjects->contains(this));
     137}
     138
     139ParserRefCounted::~ParserRefCounted()
     140{
     141#ifndef NDEBUG
     142    --ParserRefCountedCounter::count;
     143#endif
     144}
     145
     146void ParserRefCounted::ref()
     147{
     148    // bumping from 0 to 1 is just removing from the new nodes set
     149    if (newTrackedObjects) {
     150        HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->find(this);
     151        if (it != newTrackedObjects->end()) {
     152            newTrackedObjects->remove(it);
     153            ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
     154            return;
     155        }
     156    }   
     157
     158    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
     159   
     160    if (!trackedObjectExtraRefCounts)
     161        trackedObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
     162    trackedObjectExtraRefCounts->add(this);
     163}
     164
     165void ParserRefCounted::deref()
     166{
     167    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
     168   
     169    if (!trackedObjectExtraRefCounts) {
     170        delete this;
     171        return;
     172    }
     173
     174    HashCountedSet<ParserRefCounted*>::iterator it = trackedObjectExtraRefCounts->find(this);
     175    if (it == trackedObjectExtraRefCounts->end())
     176        delete this;
     177    else
     178        trackedObjectExtraRefCounts->remove(it);
     179}
     180
     181unsigned ParserRefCounted::refcount()
     182{
     183    if (newTrackedObjects && newTrackedObjects->contains(this)) {
     184        ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
     185        return 0;
     186    }
     187 
     188    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
     189
     190    if (!trackedObjectExtraRefCounts)
     191        return 1;
     192
     193    return 1 + trackedObjectExtraRefCounts->count(this);
     194}
     195
     196void ParserRefCounted::deleteNewObjects()
     197{
     198    if (!newTrackedObjects)
     199        return;
     200
     201#ifndef NDEBUG
     202    HashSet<ParserRefCounted*>::iterator end = newTrackedObjects->end();
     203    for (HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->begin(); it != end; ++it)
     204        ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(*it));
     205#endif
     206    deleteAllValues(*newTrackedObjects);
     207    delete newTrackedObjects;
     208    newTrackedObjects = 0;
     209}
    127210
    128211Node::Node()
     
    130213    , m_expectedReturnType(ObjectType)
    131214{
    132 #ifndef NDEBUG
    133     ++NodeCounter::count;
    134 #endif
    135215  m_line = lexer().lineNo();
    136   if (!newNodes)
    137       newNodes = new HashSet<Node*>;
    138   newNodes->add(this);
    139216}
    140217
     
    143220    , m_expectedReturnType(expectedReturn)
    144221{
    145 #ifndef NDEBUG
    146     ++NodeCounter::count;
    147 #endif
    148222    m_line = lexer().lineNo();
    149     if (!newNodes)
    150         newNodes = new HashSet<Node*>;
    151     newNodes->add(this);
    152 }
    153 
    154 Node::~Node()
    155 {
    156 #ifndef NDEBUG
    157     --NodeCounter::count;
    158 #endif
    159 }
    160 
    161 void Node::ref()
    162 {
    163     // bumping from 0 to 1 is just removing from the new nodes set
    164     if (newNodes) {
    165         HashSet<Node*>::iterator it = newNodes->find(this);
    166         if (it != newNodes->end()) {
    167             newNodes->remove(it);
    168             ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
    169             return;
    170         }
    171     }   
    172 
    173     ASSERT(!newNodes || !newNodes->contains(this));
    174    
    175     if (!nodeExtraRefCounts)
    176         nodeExtraRefCounts = new HashCountedSet<Node*>;
    177     nodeExtraRefCounts->add(this);
    178 }
    179 
    180 void Node::deref()
    181 {
    182     ASSERT(!newNodes || !newNodes->contains(this));
    183    
    184     if (!nodeExtraRefCounts) {
    185         delete this;
    186         return;
    187     }
    188 
    189     HashCountedSet<Node*>::iterator it = nodeExtraRefCounts->find(this);
    190     if (it == nodeExtraRefCounts->end())
    191         delete this;
    192     else
    193         nodeExtraRefCounts->remove(it);
    194 }
    195 
    196 unsigned Node::refcount()
    197 {
    198     if (newNodes && newNodes->contains(this)) {
    199         ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
    200         return 0;
    201     }
    202  
    203     ASSERT(!newNodes || !newNodes->contains(this));
    204 
    205     if (!nodeExtraRefCounts)
    206         return 1;
    207 
    208     return 1 + nodeExtraRefCounts->count(this);
    209 }
    210 
    211 void Node::clearNewNodes()
    212 {
    213     if (!newNodes)
    214         return;
    215 
    216 #ifndef NDEBUG
    217     HashSet<Node*>::iterator end = newNodes->end();
    218     for (HashSet<Node*>::iterator it = newNodes->begin(); it != end; ++it)
    219         ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(*it));
    220 #endif
    221     deleteAllValues(*newNodes);
    222     delete newNodes;
    223     newNodes = 0;
    224223}
    225224
     
    44014400// ------------------------------ FunctionBodyNode -----------------------------
    44024401
    4403 ScopeNode::ScopeNode(SourceElements* children)
     4402ScopeNode::ScopeNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
    44044403    : BlockNode(children)
    44054404    , m_sourceURL(parser().sourceURL())
    44064405    , m_sourceId(parser().sourceId())
    44074406{
    4408 }
    4409 
    4410 ProgramNode::ProgramNode(SourceElements* children)
    4411     : ScopeNode(children)
    4412 {
    4413 }
    4414 
    4415 EvalNode::EvalNode(SourceElements* children)
    4416     : ScopeNode(children)
    4417 {
    4418 }
    4419 
    4420 FunctionBodyNode::FunctionBodyNode(SourceElements* children)
    4421     : ScopeNode(children)
     4407    if (varStack)
     4408        m_varStack = *varStack;
     4409
     4410    if (funcStack)
     4411        m_functionStack = *funcStack;
     4412}
     4413
     4414ProgramNode::ProgramNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
     4415    : ScopeNode(children, varStack, funcStack)
     4416{
     4417}
     4418
     4419EvalNode::EvalNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
     4420    : ScopeNode(children, varStack, funcStack)
     4421{
     4422}
     4423
     4424FunctionBodyNode::FunctionBodyNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
     4425    : ScopeNode(children, varStack, funcStack)
    44224426    , m_initialized(false)
    44234427{
    44244428}
    44254429
    4426 void ScopeNode::initializeDeclarationStacks(ExecState* exec)
    4427 {
    4428     DeclarationStacks::NodeStack nodeStack;
    4429     DeclarationStacks stacks(exec, nodeStack, m_varStack, m_functionStack);
    4430     Node* node = statementListInitializeDeclarationStack(*m_children, nodeStack);
    4431     if (!node)
    4432         return;
    4433    
    4434     while (true) {
    4435         ASSERT(node->mayHaveDeclarations()); // Otherwise, we wasted time putting an irrelevant node on the stack.
    4436         node->getDeclarations(stacks);
    4437        
    4438         size_t size = nodeStack.size();
    4439         if (!size)
    4440             break;
    4441         --size;
    4442         node = nodeStack[size];
    4443         nodeStack.shrink(size);
    4444     }
    4445 }
    4446 
    4447 void FunctionBodyNode::initializeSymbolTable()
     4430void FunctionBodyNode::initializeSymbolTable(ExecState* exec)
    44484431{
    44494432    size_t i, size;
     
    44514434
    44524435    // The order of additions here implicitly enforces the mutual exclusion described in ECMA 10.1.3.
    4453     for (i = 0, size = m_varStack.size(); i < size; ++i)
    4454         m_symbolTable.set(m_varStack[i]->ident.ustring().rep(), count++);
     4436    for (i = 0, size = m_varStack.size(); i < size; ++i) {
     4437        if (m_varStack[i]->ident != exec->propertyNames().arguments)
     4438            m_symbolTable.set(m_varStack[i]->ident.ustring().rep(), count);
     4439        count++;
     4440    }
    44554441
    44564442    for (i = 0, size = m_parameters.size(); i < size; ++i)
     
    44834469{
    44844470    if (!m_initialized) {
    4485         initializeDeclarationStacks(exec);
    4486         initializeSymbolTable();
     4471        initializeSymbolTable(exec);
    44874472        optimizeVariableAccess();
    44884473       
     
    45214506void ProgramNode::processDeclarations(ExecState* exec)
    45224507{
    4523     initializeDeclarationStacks(exec);
    4524 
    45254508    size_t i, size;
    45264509
     
    45474530void EvalNode::processDeclarations(ExecState* exec)
    45484531{
    4549     initializeDeclarationStacks(exec);
    4550 
    45514532    size_t i, size;
    45524533
  • trunk/JavaScriptCore/kjs/nodes.h

    r28608 r28854  
    112112  };
    113113
    114   class Node : Noncopyable {
    115   public:
    116     Node() KJS_FAST_CALL;
    117     Node(PlacementNewAdoptType) KJS_FAST_CALL { }
    118     virtual ~Node();
    119 
    120     UString toString() const KJS_FAST_CALL;
    121     int lineNo() const KJS_FAST_CALL { return m_line; }
     114  class ParserRefCounted : Noncopyable {
     115  protected:
     116    ParserRefCounted() KJS_FAST_CALL;
     117    ParserRefCounted(PlacementNewAdoptType) KJS_FAST_CALL { }
     118   
     119  public:
    122120    void ref() KJS_FAST_CALL;
    123121    void deref() KJS_FAST_CALL;
    124122    unsigned refcount() KJS_FAST_CALL;
    125     static void clearNewNodes() KJS_FAST_CALL;
     123   
     124    static void deleteNewObjects() KJS_FAST_CALL;
     125 
     126    virtual ~ParserRefCounted();
     127  };
     128
     129  class Node : public ParserRefCounted {
     130  public:
     131    Node() KJS_FAST_CALL;
     132    Node(PlacementNewAdoptType placementAdopt) KJS_FAST_CALL
     133    : ParserRefCounted(placementAdopt) { }
     134
     135    UString toString() const KJS_FAST_CALL;
     136    int lineNo() const KJS_FAST_CALL { return m_line; }
    126137
    127138    // Serialization.
     
    18451856    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    18461857    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
     1858    VarDeclNode* getVarDecl() { return varDecl.get(); }
    18471859  private:
    18481860    Identifier ident;
     
    19521964  class ScopeNode : public BlockNode {
    19531965  public:
    1954     ScopeNode(SourceElements*) KJS_FAST_CALL;
     1966    ScopeNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
    19551967
    19561968    int sourceId() KJS_FAST_CALL { return m_sourceId; }
     
    19581970
    19591971  protected:
    1960     void initializeDeclarationStacks(ExecState*) KJS_FAST_CALL;
    19611972
    19621973    DeclarationStacks::VarStack m_varStack;
     
    19701981  class ProgramNode : public ScopeNode {
    19711982  public:
    1972     ProgramNode(SourceElements*) KJS_FAST_CALL;
     1983    ProgramNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
    19731984    virtual Completion execute(ExecState*) KJS_FAST_CALL;
    19741985   
     
    19791990  class EvalNode : public ScopeNode {
    19801991  public:
    1981     EvalNode(SourceElements*) KJS_FAST_CALL;
     1992    EvalNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
    19821993    virtual Completion execute(ExecState*) KJS_FAST_CALL;
    19831994   
     
    19881999  class FunctionBodyNode : public ScopeNode {
    19892000  public:
    1990     FunctionBodyNode(SourceElements*) KJS_FAST_CALL;
     2001    FunctionBodyNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
    19912002
    19922003    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     
    19982009
    19992010  private:
    2000     void initializeSymbolTable() KJS_FAST_CALL;
     2011    void initializeSymbolTable(ExecState*) KJS_FAST_CALL;
    20012012    void optimizeVariableAccess() KJS_FAST_CALL;
    20022013    ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
Note: See TracChangeset for help on using the changeset viewer.