Changeset 24532 in webkit for trunk/JavaScriptCore/kjs/nodes.cpp


Ignore:
Timestamp:
Jul 23, 2007, 12:10:35 AM (18 years ago)
Author:
mjs
Message:

Reviewed by Darin.

-fixed <rdar://problem/5353293> REGRESSION (r24287): 1% i-Bench JS slowdown from JavaScript compatibility fix (14719)
http://bugs.webkit.org/show_bug.cgi?id=14719


My fix for this actually resulted in JS iBench being 1% faster than before the regression
and the Celtic Kane benchmark being 5% faster than before the regression.


  • kjs/nodes.cpp: (VarDeclNode::handleSlowCase): factored out the slow code path to be out of line. (VarDeclNode::evaluate): I did a couple of things: (1) Don't check if the variable is already declared by looking for the property in the variable object, that code path was dead code. (2) Special-case the common case where the top of the scope and the variable object are the same; in that case the variable must always be in the variable object. (3) Don't return a jsString() of the variable name, nothing uses the return value from this node types evaluate method.
  • kjs/nodes.h:
File:
1 edited

Legend:

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

    r24287 r24532  
    15881588}
    15891589
     1590JSValue* VarDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val)
     1591{
     1592    ScopeChainIterator iter = chain.begin();
     1593    ScopeChainIterator end = chain.end();       
     1594   
     1595    // we must always have something in the scope chain
     1596    ASSERT(iter != end);
     1597   
     1598    PropertySlot slot;
     1599    JSObject* base;
     1600   
     1601    do {
     1602        base = *iter;
     1603        if (base->getPropertySlot(exec, ident, slot))
     1604            break;
     1605       
     1606        ++iter;
     1607    } while (iter != end);
     1608   
     1609    unsigned flags = 0;
     1610    base->getPropertyAttributes(ident, flags);
     1611    if (varType == VarDeclNode::Constant)
     1612        flags |= ReadOnly;
     1613   
     1614    base->put(exec, ident, val, flags);
     1615    return 0;
     1616}
     1617
    15901618// ECMA 12.2
    1591 JSValue *VarDeclNode::evaluate(ExecState *exec)
    1592 {
    1593   JSObject* variable = exec->context()->variableObject();
    1594 
    1595   JSValue* val;
    1596   if (init) {
    1597       val = init->evaluate(exec);
    1598       KJS_CHECKEXCEPTIONVALUE
    1599      
    1600       if (variable->getDirect(ident) || ident == exec->propertyNames().arguments) {
    1601           const ScopeChain& chain = exec->context()->scopeChain();
    1602           ScopeChainIterator iter = chain.begin();
    1603           ScopeChainIterator end = chain.end();       
    1604 
    1605           // we must always have something in the scope chain
    1606           ASSERT(iter != end);
    1607 
    1608           PropertySlot slot;
    1609           JSObject* base;
    1610 
    1611           do {
    1612               base = *iter;
    1613               if (base->getPropertySlot(exec, ident, slot))
    1614                   break;
    1615 
    1616              ++iter;
    1617           } while (iter != end);
    1618 
    1619           unsigned flags = 0;
    1620           base->getPropertyAttributes(ident, flags);
    1621           if (varType == VarDeclNode::Constant)
    1622               flags |= ReadOnly;
    1623 
    1624           base->put(exec, ident, val, flags);
    1625           return jsString(ident.ustring());
    1626       }
    1627     } else {
    1628       // already declared? - check with getDirect so you can override
    1629       // built-in properties of the global object with var declarations.
    1630       // Also check for 'arguments' property. The 'arguments' cannot be found with
    1631       // getDirect, because it's created lazily by
    1632       // ActivationImp::getOwnPropertySlot.
    1633       // Since variable declarations are always in function scope, 'variable'
    1634       // will always contain instance of ActivationImp and ActivationImp will
    1635       // always have 'arguments' property
    1636       if (variable->getDirect(ident) || ident == exec->propertyNames().arguments)
    1637           return 0;
    1638       val = jsUndefined();
    1639   }
    1640 
    1641 #ifdef KJS_VERBOSE
    1642   printInfo(exec,(UString("new variable ")+ident.ustring()).cstring().c_str(),val);
    1643 #endif
    1644   // We use Internal to bypass all checks in derived objects, e.g. so that
    1645   // "var location" creates a dynamic property instead of activating window.location.
    1646   int flags = Internal;
    1647   if (exec->context()->codeType() != EvalCode)
    1648     flags |= DontDelete;
    1649   if (varType == VarDeclNode::Constant)
    1650     flags |= ReadOnly;
    1651   variable->put(exec, ident, val, flags);
    1652 
    1653   return jsString(ident.ustring());
     1619JSValue* VarDeclNode::evaluate(ExecState* exec)
     1620{
     1621    JSValue* val;
     1622    if (init) {
     1623        val = init->evaluate(exec);
     1624        KJS_CHECKEXCEPTIONVALUE
     1625           
     1626        const ScopeChain& chain = exec->context()->scopeChain();
     1627        JSObject* variableObject = exec->context()->variableObject();
     1628
     1629        ASSERT(!chain.isEmpty());
     1630        ASSERT(variableObject->getDirect(ident) || ident == exec->propertyNames().arguments);
     1631
     1632        // if the variable object is the top of the scope chain, then that must
     1633        // be where this variable is declared, processVarDecls would have put
     1634        // it there. Don't search the scope chain, to optimize this very common case.
     1635        if (chain.top() != variableObject)
     1636            return handleSlowCase(exec, chain, val);
     1637
     1638        unsigned flags = 0;
     1639        variableObject->getPropertyAttributes(ident, flags);
     1640        if (varType == VarDeclNode::Constant)
     1641            flags |= ReadOnly;
     1642       
     1643        variableObject->put(exec, ident, val, flags);
     1644    }
     1645
     1646    // no caller of this function actually uses the return value.
     1647    // FIXME: It would be better to change the inheritence hierarchy so this
     1648    // node doesn't even have an evaluate method, but instead a differently named
     1649    // one with a void return.
     1650    return 0;
    16541651}
    16551652
Note: See TracChangeset for help on using the changeset viewer.