Added nodes to allow Assignment, TypeOf, and prefix operators to
authoroliver <oliver@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 29 Oct 2007 07:05:49 +0000 (07:05 +0000)
committeroliver <oliver@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 29 Oct 2007 07:05:49 +0000 (07:05 +0000)
make use of the new optimised local variable look up.

5% gain on sunspider

Reviewed by Darin

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27216 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/nodes.h

index 52faf92f7130f86f5bbb742e8496d155b8acf96c..0d13cf0ef12fd4b4f1ab2595230e98f9b0a9ac39 100644 (file)
@@ -1,3 +1,29 @@
+2007-10-28  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Darin.
+
+        Add nodes to allow Assignment, TypeOf, and prefix operators to 
+        make use of the new optimised local variable look up.
+
+        5% gain on sunspider
+
+        * kjs/nodes.cpp:
+        (KJS::TypeOfResolveNode::optimizeVariableAccess):
+        (KJS::LocalTypeOfAccessNode::evaluate):
+        (KJS::PrefixResolveNode::optimizeVariableAccess):
+        (KJS::PrefixLocalAccessNode::evaluate):
+        (KJS::AssignResolveNode::optimizeVariableAccess):
+        (KJS::AssignLocalAccessNode::evaluate):
+        * kjs/nodes.h:
+        (KJS::TypeOfResolveNode::):
+        (KJS::TypeOfResolveNode::precedence):
+        (KJS::LocalTypeOfAccessNode::):
+        (KJS::PrefixResolveNode::):
+        (KJS::PrefixResolveNode::precedence):
+        (KJS::PrefixLocalAccessNode::):
+        (KJS::AssignResolveNode::):
+        (KJS::AssignLocalAccessNode::):
+
 2007-10-28  Maciej Stachowiak  <mjs@apple.com>
 
         Reviewed by Darin.
index 58b669d1f1bc490ffc44b13c83a6e76bdafa7094..7a9e81b961e9ebd952f839b431f05ecd85858121 100644 (file)
@@ -1176,6 +1176,21 @@ static JSValue *typeStringForValue(JSValue *v)
     }
 }
 
+void TypeOfResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
+{
+    size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
+    if (index != missingSymbolMarker())
+        new (this) LocalTypeOfAccessNode(index);
+}
+
+JSValue* LocalTypeOfAccessNode::evaluate(ExecState* exec)
+{
+    ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
+    ASSERT(variableObject->isActivation());
+    ASSERT(variableObject == exec->scopeChain().top());
+    return typeStringForValue(variableObject->localStorage()[m_index].value);
+}
+
 JSValue *TypeOfResolveNode::evaluate(ExecState *exec)
 {
   const ScopeChain& chain = exec->scopeChain();
@@ -1214,6 +1229,28 @@ JSValue *TypeOfValueNode::evaluate(ExecState *exec)
 
 // ------------------------------ PrefixResolveNode ----------------------------------
 
+void PrefixResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
+{
+    size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
+    if (index != missingSymbolMarker())
+        new (this) PrefixLocalAccessNode(index);
+}
+
+JSValue* PrefixLocalAccessNode::evaluate(ExecState* exec)
+{
+    ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
+    ASSERT(variableObject->isActivation());
+    ASSERT(variableObject == exec->scopeChain().top());
+    JSValue* v = variableObject->localStorage()[m_index].value;
+
+    double n = v->toNumber(exec);
+        
+    double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
+    JSValue* n2 = jsNumber(newValue);
+    variableObject->localStorage()[m_index].value = n2;
+    return n2;
+}
+
 JSValue *PrefixResolveNode::evaluate(ExecState *exec)
 {
   const ScopeChain& chain = exec->scopeChain();
@@ -1963,9 +2000,34 @@ static ALWAYS_INLINE JSValue *valueForReadModifyAssignment(ExecState * exec, JSV
 
 // ------------------------------ AssignResolveNode -----------------------------------
 
-void AssignResolveNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
+void AssignResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack& nodeStack)
 {
     nodeStack.append(m_right.get());
+    size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
+    if (index != missingSymbolMarker())
+        new (this) AssignLocalAccessNode(index);
+}
+
+JSValue* AssignLocalAccessNode::evaluate(ExecState* exec)
+{
+    ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
+    ASSERT(variableObject->isActivation());
+    ASSERT(variableObject == exec->scopeChain().top());
+    JSValue* v;
+
+    if (m_oper == OpEqual)
+        v = m_right->evaluate(exec);
+    else {
+        JSValue* v1 = variableObject->localStorage()[m_index].value;
+        KJS_CHECKEXCEPTIONVALUE
+        JSValue* v2 = m_right->evaluate(exec);
+        v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
+    }
+
+    KJS_CHECKEXCEPTIONVALUE
+
+    variableObject->localStorage()[m_index].value = v;
+    return v;
 }
 
 JSValue *AssignResolveNode::evaluate(ExecState *exec)
index 86146c650f605f0f7bfbc5cc8a2f97397bd95bdc..53053095bf7b7dacec1cc6a7895fd53dfc9048ef 100644 (file)
@@ -683,12 +683,40 @@ namespace KJS {
 
   class TypeOfResolveNode : public Node {
   public:
-    TypeOfResolveNode(const Identifier& i) KJS_FAST_CALL : m_ident(i) {}
+    TypeOfResolveNode(const Identifier &s) KJS_FAST_CALL 
+        : m_ident(s) 
+    { 
+    }
+    
+    TypeOfResolveNode(PlacementNewAdoptType) KJS_FAST_CALL 
+        : Node(PlacementNewAdopt)
+        , m_ident(PlacementNewAdopt) 
+    {
+    }
+
+    virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
+    
     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     virtual Precedence precedence() const { return PrecUnary; }
-  private:
+
+    const Identifier& identifier() const KJS_FAST_CALL { return m_ident; }
+
+  protected:
     Identifier m_ident;
+    size_t m_index; // Used by LocalTypeOfNode.
+  };
+    
+  class LocalTypeOfAccessNode : public TypeOfResolveNode {
+  public:
+    LocalTypeOfAccessNode(size_t i) KJS_FAST_CALL 
+        : TypeOfResolveNode(PlacementNewAdopt)
+    { 
+        ASSERT(i != missingSymbolMarker());
+        m_index = i;
+    }
+
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
   };
 
   class TypeOfValueNode : public Node {
@@ -704,13 +732,41 @@ namespace KJS {
 
   class PrefixResolveNode : public Node {
   public:
-    PrefixResolveNode(const Identifier& i, Operator o) KJS_FAST_CALL : m_ident(i), m_oper(o) {}
+    PrefixResolveNode(const Identifier &s, Operator o) KJS_FAST_CALL 
+        : m_ident(s) 
+        , m_oper(o) 
+    { 
+    }
+    
+    PrefixResolveNode(PlacementNewAdoptType) KJS_FAST_CALL 
+        : Node(PlacementNewAdopt)
+        , m_ident(PlacementNewAdopt) 
+        , m_oper(m_oper) 
+    {
+    }
+    
+    virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
+
     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     virtual Precedence precedence() const { return PrecUnary; }
-  private:
+
+  protected:
     Identifier m_ident;
     Operator m_oper;
+    size_t m_index;
+  };
+
+  class PrefixLocalAccessNode : public PrefixResolveNode {
+  public:
+    PrefixLocalAccessNode(size_t i) KJS_FAST_CALL 
+        : PrefixResolveNode(PlacementNewAdopt)
+    { 
+        ASSERT(i != missingSymbolMarker());
+        m_index = i;
+    }
+    
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
   };
 
   class PrefixBracketNode : public Node {
@@ -1111,7 +1167,20 @@ namespace KJS {
   class AssignResolveNode : public Node {
   public:
     AssignResolveNode(const Identifier &ident, Operator oper, Node *right) KJS_FAST_CALL
-      : m_ident(ident), m_oper(oper), m_right(right) {}
+      : m_ident(ident)
+      , m_oper(oper)
+      , m_right(right) 
+      {
+      }
+
+    AssignResolveNode(PlacementNewAdoptType) KJS_FAST_CALL 
+      : Node(PlacementNewAdopt)
+      , m_ident(PlacementNewAdopt) 
+      , m_oper(m_oper) 
+      , m_right(PlacementNewAdopt) 
+    {
+    }
+
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -1120,6 +1189,19 @@ namespace KJS {
     Identifier m_ident;
     Operator m_oper;
     RefPtr<Node> m_right;
+    size_t m_index;
+  };
+
+  class AssignLocalAccessNode : public AssignResolveNode {
+  public:
+    AssignLocalAccessNode(size_t i) KJS_FAST_CALL 
+        : AssignResolveNode(PlacementNewAdopt)
+    { 
+        ASSERT(i != missingSymbolMarker());
+        m_index = i;
+    }
+    
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
   };
 
   class AssignBracketNode : public Node {