+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.
}
}
+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();
// ------------------------------ 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();
// ------------------------------ 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)
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 {
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 {
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;
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 {