Changeset 27025 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Oct 25, 2007, 12:09:44 AM (18 years ago)
Author:
ggaren
Message:

JavaScriptCore:

Reviewed by Maciej Stachowiak.


Fixed http://bugs.webkit.org/show_bug.cgi?id=15683
Re-order declaration initialization to avoid calling hasProperty inside
VarDeclNode::processDeclaration


.7% speedup on SunSpider.

  • kjs/function.h:
  • kjs/function.cpp: Merged parameter processing into FunctionBodyNode's other processing of declared symbols, so the order of execution could change.
  • kjs/nodes.cpp: (KJS::VarDeclNode::getDeclarations): Added special case for the "arguments" property name, explained in the comment.

(KJS::VarDeclNode::processDeclaration): Removed call to hasProperty
in the case of function code, since we know the declared symbol
management will resolve conflicts between symbols. Yay!

(KJS::VarDeclListNode::getDeclarations): Now that VarDeclNode's
implementation of getDeclarations is non-trivial, we can't take a
short-cut here any longer -- we need to put the VarDecl node on the
stack so it gets processed normally.

(KJS::FunctionBodyNode::processDeclarations): Changed the order of
processing to enforce mutual exclusion rules.

  • kjs/nodes.h: (KJS::DeclarationStacks::DeclarationStacks): Structure includes an ExecState now, for fast access to the "arguments" property name.

LayoutTests:

Layout tests for bugs that might result from changes like
http://bugs.webkit.org/show_bug.cgi?id=15683

  • fast/js/vardecl-preserve-parameters-expected.txt: Added.
  • fast/js/vardecl-preserve-parameters.html: Added.
  • fast/js/vardecl-preserve-vardecl-expected.txt: Added.
  • fast/js/vardecl-preserve-vardecl.html: Added.
Location:
trunk/JavaScriptCore/kjs
Files:
4 edited

Legend:

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

    r27022 r27025  
    7777  ctx.setExecState(&newExec);
    7878
    79   passInParameters(&newExec, args);
    80 
    8179  Debugger* dbg = exec->dynamicInterpreter()->debugger();
    8280  int sid = -1;
     
    125123  else
    126124    return jsUndefined();
    127 }
    128 
    129 // ECMA 10.1.3q
    130 inline void FunctionImp::passInParameters(ExecState* exec, const List& args)
    131 {
    132     Vector<Identifier>& parameters = body->parameters();
    133 
    134     JSObject* variable = exec->context()->variableObject();
    135 
    136     size_t size = parameters.size();
    137     for (size_t i = 0; i < size; ++i) {
    138       variable->put(exec, parameters[i], args[i], DontDelete);
    139     }
    140125}
    141126
  • trunk/JavaScriptCore/kjs/function.h

    r26808 r27025  
    108108    static JSValue* callerGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
    109109    static JSValue* lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
    110 
    111     void passInParameters(ExecState*, const List&);
    112110  };
    113111
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r27001 r27025  
    17671767
    17681768void VarDeclNode::getDeclarations(DeclarationStacks& stacks)
    1769 {
     1769{
     1770    // The normal check to avoid overwriting pre-existing values with variable
     1771    // declarations doesn't work for the "arguments" property because we
     1772    // instantiate it lazily. So we need to check here instead.
     1773    if (ident == stacks.exec->propertyNames().arguments)
     1774        return;
     1775
    17701776    stacks.varStack.append(this);
    17711777}
     
    18451851void VarDeclNode::processDeclaration(ExecState* exec)
    18461852{
    1847   JSObject* variable = exec->context()->variableObject();
    1848 
    1849   // If a variable by this name already exists, don't clobber it -
    1850   // it might be a function parameter
    1851   if (!variable->hasProperty(exec, ident)) {
    1852     int flags = Internal;
    1853     if (exec->context()->codeType() != EvalCode)
    1854       flags |= DontDelete;
    1855     if (varType == VarDeclNode::Constant)
    1856       flags |= ReadOnly;
    1857     variable->put(exec, ident, jsUndefined(), flags);
    1858   }
     1853  Context* context = exec->context();
     1854  JSObject* variable = context->variableObject();
     1855
     1856  if (context->codeType() != FunctionCode)
     1857    if (variable->hasProperty(exec, ident))
     1858        return;
     1859
     1860  int flags = Internal;
     1861  if (context->codeType() != EvalCode)
     1862    flags |= DontDelete;
     1863  if (varType == VarDeclNode::Constant)
     1864    flags |= ReadOnly;
     1865  variable->put(exec, ident, jsUndefined(), flags);
    18591866}
    18601867
     
    18771884        stacks.nodeStack.append(next.get());
    18781885    }
    1879     stacks.varStack.append(var.get());
     1886    stacks.nodeStack.append(var.get());
    18801887}
    18811888
     
    25962603}
    25972604
    2598 void FunctionBodyNode::initializeDeclarationStacks()
     2605void FunctionBodyNode::initializeDeclarationStacks(ExecState* exec)
    25992606{
    26002607    Node* node = source.get();
     
    26032610
    26042611    DeclarationStacks::NodeStack nodeStack;
    2605     DeclarationStacks stacks(nodeStack, m_varStack, m_functionStack);
     2612    DeclarationStacks stacks(exec, nodeStack, m_varStack, m_functionStack);
    26062613   
    26072614    while (true) {
     
    26232630{
    26242631    if (!m_initializedDeclarationStacks)
    2625         initializeDeclarationStacks();
     2632        initializeDeclarationStacks(exec);
    26262633
    26272634    size_t i, size;
     2635
     2636    JSObject* variableObject = exec->context()->variableObject();
     2637    const List& args = *exec->context()->arguments();
     2638
     2639    // The order of additions to the variable object here implicitly enforces the mutual exclusion described in ECMA 10.1.3.
     2640    for (i = 0, size = m_varStack.size(); i < size; ++i)
     2641        m_varStack[i]->processDeclaration(exec);
     2642
     2643    for (i = 0, size = m_parameters.size(); i < size; ++i)
     2644        variableObject->put(exec, m_parameters[i], args[i], DontDelete);
    26282645
    26292646    for (i = 0, size = m_functionStack.size(); i < size; ++i)
    26302647        m_functionStack[i]->processDeclaration(exec);
    2631 
    2632     for (i = 0, size = m_varStack.size(); i < size; ++i)
    2633         m_varStack[i]->processDeclaration(exec);
    26342648}
    26352649
  • trunk/JavaScriptCore/kjs/nodes.h

    r26960 r27025  
    8989      typedef Vector<FuncDeclNode*, 16> FunctionStack;
    9090     
    91       DeclarationStacks(NodeStack& n, VarStack& v, FunctionStack& f)
    92         : nodeStack(n)
     91      DeclarationStacks(ExecState* e, NodeStack& n, VarStack& v, FunctionStack& f)
     92        : exec(e)
     93        , nodeStack(n)
    9394        , varStack(v)
    9495        , functionStack(f)
    9596      {
    9697      }
    97        
     98
     99      ExecState* exec;
    98100      NodeStack& nodeStack;
    99101      VarStack& varStack;
     
    12441246    UString m_sourceURL;
    12451247    int m_sourceId;
    1246     Vector<Identifier> m_parameters;
    1247 
    1248     void initializeDeclarationStacks();
     1248
     1249    void initializeDeclarationStacks(ExecState*);
    12491250    bool m_initializedDeclarationStacks;
     1251
    12501252    DeclarationStacks::VarStack m_varStack;
    12511253    DeclarationStacks::FunctionStack m_functionStack;
     1254    Vector<Identifier> m_parameters;
    12521255  };
    12531256
Note: See TracChangeset for help on using the changeset viewer.