Changeset 26682 in webkit for trunk/JavaScriptCore/kjs/nodes.h


Ignore:
Timestamp:
Oct 16, 2007, 2:35:50 PM (18 years ago)
Author:
ggaren
Message:

JavaScriptCore:

Reviewed by Maciej Stachowiak.


Re-structured variable and function declaration code.


Command-line JS iBench shows no regression.


Here are the changes:

  1. Function declarations are now processed at the same time as var declarations -- namely, immediately upon entry to an execution context. This does not match Firefox, which waits to process a function declaration until the declaration's containing block executes, but it does match IE and the ECMA spec. (10.1.3 states that var and function declarations should be processed at the same time -- namely, "On entering an execution context." 12.2 states that "A Block does not define a new execution scope.")
  1. Declaration processing proceeds iteratively now, rather than recursively, storing the nodes is finds in stacks. This will later facilitate an optimization to hold on to the gathered declaration nodes, rather than re-fetching them in every function call. [ http://bugs.webkit.org/show_bug.cgi?id=14868 ]

Modified these tests because they expected the incorrect Mozilla
behavior described above:

  • tests/mozilla/ecma_3/Function/scope-001.js:
  • tests/mozilla/js1_5/Scope/regress-184107.js:

LayoutTests:

Reviewed by Maciej Stachowiak.


Layout tests for http://bugs.webkit.org/show_bug.cgi?id=15478
Declare vars and functions iteratively upon entering an execution context

  • fast/js/function-declarations-expected.txt: Added.
  • fast/js/function-declarations.html: Added.
  • fast/js/var-declarations-expected.txt: Added.
  • fast/js/var-declarations.html: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/nodes.h

    r26582 r26682  
    4545namespace KJS {
    4646
     47  class FuncDeclNode;
    4748  class ProgramNode;
    4849  class PropertyNameNode;
     
    5152  class SourceElementsNode;
    5253  class SourceStream;
     54  class VarDeclNode;
    5355
    5456  enum Operator { OpEqual,
     
    8284                  OpInstanceOf
    8385  };
     86 
     87  struct DeclarationStacks {
     88      typedef Vector<Node*, 16> NodeStack;
     89      typedef Vector<VarDeclNode*, 16> VarStack;
     90      typedef Vector<FuncDeclNode*, 16> FunctionStack;
     91     
     92      NodeStack nodeStack;
     93      VarStack varStack;
     94      FunctionStack functionStack;
     95  };
    8496
    8597  class Node {
     
    91103    UString toString() const KJS_FAST_CALL;
    92104    virtual void streamTo(SourceStream&) const KJS_FAST_CALL = 0;
    93     virtual void processVarDecls(ExecState*) KJS_FAST_CALL {}
    94105    int lineNo() const KJS_FAST_CALL { return m_line; }
    95 
    96106    void ref() KJS_FAST_CALL;
    97107    void deref() KJS_FAST_CALL;
     
    107117    virtual bool isDotAccessorNode() const KJS_FAST_CALL { return false; }
    108118    virtual bool isGroupNode() const KJS_FAST_CALL { return false; }
     119
     120    // Used for iterative, depth-first traversal of the node tree. Does not cross function call boundaries.
     121    bool mayHaveDeclarations() { return m_mayHaveDeclarations; }
     122    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL { ASSERT_NOT_REACHED(); }
    109123
    110124    virtual void breakCycle() KJS_FAST_CALL { }
     
    127141    void handleException(ExecState*, JSValue*) KJS_FAST_CALL;
    128142
    129     int m_line;
     143    int m_line : 31;
     144    bool m_mayHaveDeclarations : 1;
    130145  private:
    131146    // disallow assignment
     
    143158    virtual Completion execute(ExecState *exec) KJS_FAST_CALL = 0;
    144159    void pushLabel(const Identifier &id) KJS_FAST_CALL { ls.push(id); }
    145     virtual void processFuncDecl(ExecState*) KJS_FAST_CALL;
    146160  protected:
    147161    LabelStack ls;
     
    800814    VarDeclNode(const Identifier &id, AssignExprNode *in, Type t) KJS_FAST_CALL;
    801815    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    802     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    803     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     816    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     817    void ALWAYS_INLINE processDeclaration(ExecState*) KJS_FAST_CALL;
     818    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    804819  private:
    805820    JSValue* handleSlowCase(ExecState*, const ScopeChain&, JSValue*) KJS_FAST_CALL KJS_NO_INLINE;
     
    812827  public:
    813828    // list pointer is tail of a circular list, cracked in the ForNode/VarStatementNode ctor
    814     VarDeclListNode(VarDeclNode *v) KJS_FAST_CALL : next(this), var(v) { Parser::noteNodeCycle(this); }
     829    VarDeclListNode(VarDeclNode *v) KJS_FAST_CALL : next(this), var(v) { Parser::noteNodeCycle(this); m_mayHaveDeclarations = true; }
    815830    VarDeclListNode(VarDeclListNode *l, VarDeclNode *v) KJS_FAST_CALL
    816       : next(l->next), var(v) { l->next = this; }
    817     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    818     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
     831      : next(l->next), var(v) { l->next = this; m_mayHaveDeclarations = true; }
     832    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    819833    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    820834    PassRefPtr<VarDeclListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
    821835    virtual void breakCycle() KJS_FAST_CALL;
     836    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    822837  private:
    823838    friend class ForNode;
     
    829844  class VarStatementNode : public StatementNode {
    830845  public:
    831     VarStatementNode(VarDeclListNode *l) KJS_FAST_CALL : next(l->next.release()) { Parser::removeNodeCycle(next.get()); }
    832     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    833     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    834     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     846    VarStatementNode(VarDeclListNode *l) KJS_FAST_CALL : next(l->next.release()) { Parser::removeNodeCycle(next.get()); m_mayHaveDeclarations = true; }
     847    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     848    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     849    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    835850  private:
    836851    RefPtr<VarDeclListNode> next;
     
    841856    BlockNode(SourceElementsNode *s) KJS_FAST_CALL;
    842857    virtual Completion execute(ExecState*) KJS_FAST_CALL;
    843     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    844     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     858    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     859    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    845860  protected:
    846861    RefPtr<SourceElementsNode> source;
     
    866881  public:
    867882    IfNode(Node *e, StatementNode *s1, StatementNode *s2) KJS_FAST_CALL
    868       : expr(e), statement1(s1), statement2(s2) {}
    869     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    870     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    871     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     883      : expr(e), statement1(s1), statement2(s2) { m_mayHaveDeclarations = statement1->mayHaveDeclarations() || (statement2 && statement2->mayHaveDeclarations()); }
     884    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     885    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     886    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    872887  private:
    873888    RefPtr<Node> expr;
     
    878893  class DoWhileNode : public StatementNode {
    879894  public:
    880     DoWhileNode(StatementNode *s, Node *e) KJS_FAST_CALL : statement(s), expr(e) {}
    881     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    882     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    883     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     895    DoWhileNode(StatementNode *s, Node *e) KJS_FAST_CALL : statement(s), expr(e) { m_mayHaveDeclarations = true; }
     896    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     897    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     898    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    884899  private:
    885900    RefPtr<StatementNode> statement;
     
    889904  class WhileNode : public StatementNode {
    890905  public:
    891     WhileNode(Node *e, StatementNode *s) KJS_FAST_CALL : expr(e), statement(s) {}
    892     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    893     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    894     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     906    WhileNode(Node *e, StatementNode *s) KJS_FAST_CALL : expr(e), statement(s) { m_mayHaveDeclarations = true; }
     907    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     908    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     909    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    895910  private:
    896911    RefPtr<Node> expr;
     
    901916  public:
    902917    ForNode(Node *e1, Node *e2, Node *e3, StatementNode *s) KJS_FAST_CALL :
    903       expr1(e1), expr2(e2), expr3(e3), statement(s) {}
     918      expr1(e1), expr2(e2), expr3(e3), statement(s) { m_mayHaveDeclarations = true; }
    904919    ForNode(VarDeclListNode *e1, Node *e2, Node *e3, StatementNode *s) KJS_FAST_CALL :
    905       expr1(e1->next.release()), expr2(e2), expr3(e3), statement(s) { Parser::removeNodeCycle(expr1.get()); }
    906     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    907     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    908     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     920      expr1(e1->next.release()), expr2(e2), expr3(e3), statement(s) { Parser::removeNodeCycle(expr1.get()); m_mayHaveDeclarations = true; }
     921    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     922    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     923    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    909924  private:
    910925    RefPtr<Node> expr1;
     
    919934    ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s) KJS_FAST_CALL;
    920935    virtual Completion execute(ExecState*) KJS_FAST_CALL;
    921     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    922     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     936    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     937    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    923938  private:
    924939    Identifier ident;
     
    961976  class WithNode : public StatementNode {
    962977  public:
    963     WithNode(Node *e, StatementNode *s) KJS_FAST_CALL : expr(e), statement(s) {}
    964     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    965     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    966     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     978    WithNode(Node *e, StatementNode *s) KJS_FAST_CALL : expr(e), statement(s) { m_mayHaveDeclarations = true; }
     979    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     980    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     981    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    967982  private:
    968983    RefPtr<Node> expr;
     
    972987  class LabelNode : public StatementNode {
    973988  public:
    974     LabelNode(const Identifier &l, StatementNode *s) KJS_FAST_CALL : label(l), statement(s) { }
    975     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    976     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    977     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     989    LabelNode(const Identifier &l, StatementNode *s) KJS_FAST_CALL : label(l), statement(s) { m_mayHaveDeclarations = true; }
     990    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     991    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     992    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    978993  private:
    979994    Identifier label;
     
    9931008  public:
    9941009    TryNode(StatementNode *b, const Identifier &e, StatementNode *c, StatementNode *f) KJS_FAST_CALL
    995       : tryBlock(b), exceptionIdent(e), catchBlock(c), finallyBlock(f) { }
    996     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    997     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    998     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     1010      : tryBlock(b), exceptionIdent(e), catchBlock(c), finallyBlock(f) { m_mayHaveDeclarations = true; }
     1011    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     1012    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     1013    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    9991014  private:
    10001015    RefPtr<StatementNode> tryBlock;
     
    10341049  public:
    10351050    FunctionBodyNode(SourceElementsNode *) KJS_FAST_CALL;
    1036     virtual void processFuncDecl(ExecState*) KJS_FAST_CALL;
    10371051    int sourceId() KJS_FAST_CALL { return m_sourceId; }
    10381052    const UString& sourceURL() KJS_FAST_CALL { return m_sourceURL; }
     
    10431057    UString paramString() const KJS_FAST_CALL;
    10441058    Vector<Parameter>& parameters() KJS_FAST_CALL { return m_parameters; }
     1059    void processDeclarations(ExecState*) KJS_FAST_CALL;
    10451060  private:
    10461061    UString m_sourceURL;
     
    10671082  public:
    10681083    FuncDeclNode(const Identifier &i, FunctionBodyNode *b) KJS_FAST_CALL
    1069       : ident(i), body(b) { addParams(); }
     1084      : ident(i), body(b) { addParams(); m_mayHaveDeclarations = true; }
    10701085    FuncDeclNode(const Identifier &i, ParameterNode *p, FunctionBodyNode *b) KJS_FAST_CALL
    1071       : ident(i), param(p->next.release()), body(b) { Parser::removeNodeCycle(param.get()); addParams(); }
    1072     virtual Completion execute(ExecState*) KJS_FAST_CALL;
    1073     virtual void processFuncDecl(ExecState*) KJS_FAST_CALL;
    1074     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     1086      : ident(i), param(p->next.release()), body(b) { Parser::removeNodeCycle(param.get()); addParams(); m_mayHaveDeclarations = true; }
     1087    virtual Completion execute(ExecState*) KJS_FAST_CALL;
     1088    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     1089    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
     1090    void ALWAYS_INLINE processDeclaration(ExecState*) KJS_FAST_CALL;
    10751091  private:
    10761092    void addParams() KJS_FAST_CALL;
     
    10891105   
    10901106    Completion execute(ExecState*) KJS_FAST_CALL;
    1091     void processFuncDecl(ExecState*) KJS_FAST_CALL;
    1092     virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    10931107    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    10941108    PassRefPtr<SourceElementsNode> releaseNext() KJS_FAST_CALL { return next.release(); }
    10951109    virtual void breakCycle() KJS_FAST_CALL;
     1110    virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    10961111  private:
    10971112    friend class BlockNode;
     
    11031118  class CaseClauseNode : public Node {
    11041119  public:
    1105       CaseClauseNode(Node *e) KJS_FAST_CALL : expr(e) { }
     1120      CaseClauseNode(Node *e) KJS_FAST_CALL : expr(e) { m_mayHaveDeclarations = true; }
    11061121      CaseClauseNode(Node *e, SourceElementsNode *s) KJS_FAST_CALL
    1107       : expr(e), source(s->next.release()) { Parser::removeNodeCycle(source.get()); }
     1122      : expr(e), source(s->next.release()) { Parser::removeNodeCycle(source.get()); m_mayHaveDeclarations = true; }
    11081123      JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    11091124      Completion evalStatements(ExecState*) KJS_FAST_CALL;
    1110       void processFuncDecl(ExecState*) KJS_FAST_CALL;
    1111       virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    11121125      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     1126      virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    11131127  private:
    11141128      RefPtr<Node> expr;
     
    11191133  public:
    11201134      // list pointer is tail of a circular list, cracked in the CaseBlockNode ctor
    1121       ClauseListNode(CaseClauseNode *c) KJS_FAST_CALL : clause(c), next(this) { Parser::noteNodeCycle(this); }
     1135      ClauseListNode(CaseClauseNode *c) KJS_FAST_CALL : clause(c), next(this) { Parser::noteNodeCycle(this); m_mayHaveDeclarations = true; }
    11221136      ClauseListNode(ClauseListNode *n, CaseClauseNode *c) KJS_FAST_CALL
    1123       : clause(c), next(n->next) { n->next = this; }
     1137      : clause(c), next(n->next) { n->next = this; m_mayHaveDeclarations = true; }
    11241138      JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    11251139      CaseClauseNode *getClause() const KJS_FAST_CALL { return clause.get(); }
    11261140      ClauseListNode *getNext() const KJS_FAST_CALL { return next.get(); }
    1127       virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    1128       void processFuncDecl(ExecState*) KJS_FAST_CALL;
    11291141      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    11301142      PassRefPtr<ClauseListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
    11311143      virtual void breakCycle() KJS_FAST_CALL;
     1144      virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    11321145  private:
    11331146      friend class CaseBlockNode;
     
    11411154      JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    11421155      Completion evalBlock(ExecState *exec, JSValue *input) KJS_FAST_CALL;
    1143       virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    1144       void processFuncDecl(ExecState*) KJS_FAST_CALL;
    11451156      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     1157      virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    11461158  private:
    11471159      RefPtr<ClauseListNode> list1;
     
    11521164  class SwitchNode : public StatementNode {
    11531165  public:
    1154       SwitchNode(Node *e, CaseBlockNode *b) KJS_FAST_CALL : expr(e), block(b) { }
     1166      SwitchNode(Node *e, CaseBlockNode *b) KJS_FAST_CALL : expr(e), block(b) { m_mayHaveDeclarations = true; }
    11551167      virtual Completion execute(ExecState*) KJS_FAST_CALL;
    1156       virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
    1157       virtual void processFuncDecl(ExecState*) KJS_FAST_CALL;
    11581168      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     1169      virtual void getDeclarations(DeclarationStacks&) KJS_FAST_CALL;
    11591170  private:
    11601171      RefPtr<Node> expr;
Note: See TracChangeset for help on using the changeset viewer.