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


Ignore:
Timestamp:
Oct 28, 2007, 10:32:23 PM (18 years ago)
Author:
ggaren
Message:

Reviewed by Darin Adler.


Added FunctionCallResolveNode, PostfixResolveNode, and DeleteResolveNode
to the AST transfom that replaces slow resolve nodes with fast local
variable alternatives.


2.5% speedup on SunSpider.


Also added some missing copyright notices.


  • kjs/nodes.cpp: (KJS::FunctionCallResolveNode::optimizeVariableAccess): (KJS::FunctionCallResolveNode::evaluate): (KJS::LocalVarFunctionCallNode::evaluate): (KJS::PostfixResolveNode::optimizeVariableAccess): (KJS::PostfixResolveNode::evaluate): (KJS::LocalVarPostfixNode::evaluate): (KJS::DeleteResolveNode::optimizeVariableAccess): (KJS::DeleteResolveNode::evaluate): (KJS::LocalVarDeleteNode::evaluate):
  • kjs/nodes.h: (KJS::FunctionCallResolveNode::): (KJS::LocalVarFunctionCallNode::LocalVarFunctionCallNode): (KJS::PostfixResolveNode::): (KJS::LocalVarPostfixNode::LocalVarPostfixNode): (KJS::DeleteResolveNode::): (KJS::LocalVarDeleteNode::LocalVarDeleteNode):
File:
1 edited

Legend:

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

    r27204 r27210  
    44 *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
    55 *  Copyright (C) 2007 Cameron Zwarich ([email protected])
     6 *  Copyright (C) 2007 Maks Orlovich
    67 *
    78 *  This library is free software; you can redistribute it and/or
     
    6061  }
    6162
     63#if !ASSERT_DISABLED
     64static inline bool canSkipLookup(ExecState* exec, const Identifier& ident)
     65{
     66    // Static lookup in EvalCode is impossible because variables aren't DontDelete.
     67    // Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
     68    if (exec->codeType() != FunctionCode)
     69        return false;
     70
     71    // Static lookup is impossible when something dynamic has been added to the front of the scope chain.
     72    if (exec->variableObject() != exec->scopeChain().top())
     73        return false;
     74
     75    ASSERT(exec->variableObject()->isActivation()); // Because this is function code.
     76
     77    // Static lookup is impossible if the symbol isn't statically declared.
     78    if (!static_cast<ActivationImp*>(exec->variableObject())->symbolTable().contains(ident.ustring().rep()))
     79        return false;
     80       
     81    return true;
     82}
     83#endif
     84
    6285// ------------------------------ Node -----------------------------------------
    6386
     
    375398{
    376399  // Check for missed optimization opportunity.
    377   ASSERT(exec->codeType() != FunctionCode
    378          || exec->variableObject() != exec->scopeChain().top()
    379          || (exec->variableObject()->isActivation() && !static_cast<ActivationImp*>(exec->variableObject())->symbolTable().contains(ident.ustring().rep())));
     400  ASSERT(!canSkipLookup(exec, ident));
    380401
    381402  const ScopeChain& chain = exec->scopeChain();
     
    697718}
    698719
    699 void FunctionCallResolveNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
     720void FunctionCallResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack& nodeStack)
    700721{
    701722    nodeStack.append(args.get());
     723
     724    size_t index = functionBody->symbolTable().get(ident.ustring().rep());
     725    if (index != missingSymbolMarker())
     726        new (this) LocalVarFunctionCallNode(index);
    702727}
    703728
     
    705730JSValue *FunctionCallResolveNode::evaluate(ExecState *exec)
    706731{
     732  // Check for missed optimization opportunity.
     733  ASSERT(!canSkipLookup(exec, ident));
     734
    707735  const ScopeChain& chain = exec->scopeChain();
    708736  ScopeChainIterator iter = chain.begin();
     
    751779}
    752780
     781JSValue* LocalVarFunctionCallNode::evaluate(ExecState* exec)
     782{
     783    ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
     784    ASSERT(variableObject->isActivation());
     785    ASSERT(variableObject == exec->scopeChain().top());
     786
     787    JSValue* v = variableObject->localStorage()[index].value;
     788
     789    if (!v->isObject())
     790        return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
     791     
     792    JSObject* func = static_cast<JSObject*>(v);
     793    if (!func->implementsCall())
     794        return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
     795     
     796    List argList = args->evaluateList(exec);
     797    KJS_CHECKEXCEPTIONVALUE
     798
     799    return func->call(exec, exec->dynamicInterpreter()->globalObject(), argList);
     800}
     801
    753802void FunctionCallBracketNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
    754803{
     
    859908// ------------------------------ PostfixResolveNode ----------------------------------
    860909
     910void PostfixResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
     911{
     912    size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
     913    if (index != missingSymbolMarker())
     914        new (this) LocalVarPostfixNode(index);
     915}
     916
    861917JSValue *PostfixResolveNode::evaluate(ExecState *exec)
    862918{
     919  // Check for missed optimization opportunity.
     920  ASSERT(!canSkipLookup(exec, m_ident));
     921
    863922  const ScopeChain& chain = exec->scopeChain();
    864923  ScopeChainIterator iter = chain.begin();
     
    889948}
    890949
     950JSValue* LocalVarPostfixNode::evaluate(ExecState* exec)
     951{
     952    ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
     953    ASSERT(variableObject->isActivation());
     954    ASSERT(variableObject == exec->scopeChain().top());
     955
     956    JSValue** v = &variableObject->localStorage()[index].value;
     957    double n = (*v)->toNumber(exec);
     958    double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
     959    *v = jsNumber(newValue);
     960    return jsNumber(n);
     961}
     962
    891963// ------------------------------ PostfixBracketNode ----------------------------------
    892964
     
    9701042// ------------------------------ DeleteResolveNode -----------------------------------
    9711043
     1044void DeleteResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
     1045{
     1046    size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
     1047    if (index != missingSymbolMarker())
     1048        new (this) LocalVarDeleteNode();
     1049}
     1050
    9721051// ECMA 11.4.1
    9731052
    9741053JSValue *DeleteResolveNode::evaluate(ExecState *exec)
    9751054{
     1055  // Check for missed optimization opportunity.
     1056  ASSERT(!canSkipLookup(exec, m_ident));
     1057
    9761058  const ScopeChain& chain = exec->scopeChain();
    9771059  ScopeChainIterator iter = chain.begin();
     
    9931075
    9941076  return jsBoolean(true);
     1077}
     1078
     1079JSValue* LocalVarDeleteNode::evaluate(ExecState*)
     1080{
     1081    return jsBoolean(false);
    9951082}
    9961083
Note: See TracChangeset for help on using the changeset viewer.