+2007-10-29 Oliver Hunt <oliver@apple.com>
+
+ Debranching various Node::evaluate implementations
+
+ Reviewed by Maciej.
+
+ Split the read-modify-write assignment cases out of AssignResolveNode and into ReadModifyResolveNode
+ Split the increment and decrement cases for Prefix- and Postfix- ResolveNode, BracketNode, and DotNode
+
+ Gains 1.6% on SunSpider
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::PostIncResolveNode::optimizeVariableAccess):
+ (KJS::PostIncResolveNode::evaluate):
+ (KJS::PostIncLocalVarNode::evaluate):
+ (KJS::PostDecResolveNode::optimizeVariableAccess):
+ (KJS::PostDecResolveNode::evaluate):
+ (KJS::PostDecLocalVarNode::evaluate):
+ (KJS::PostIncBracketNode::evaluate):
+ (KJS::PostDecBracketNode::evaluate):
+ (KJS::PostIncDotNode::evaluate):
+ (KJS::PostDecDotNode::evaluate):
+ (KJS::PreIncResolveNode::optimizeVariableAccess):
+ (KJS::PreIncLocalVarNode::evaluate):
+ (KJS::PreIncResolveNode::evaluate):
+ (KJS::PreDecResolveNode::optimizeVariableAccess):
+ (KJS::PreDecLocalVarNode::evaluate):
+ (KJS::PreDecResolveNode::evaluate):
+ (KJS::PreIncBracketNode::evaluate):
+ (KJS::PreDecBracketNode::evaluate):
+ (KJS::PreIncDotNode::evaluate):
+ (KJS::PreDecDotNode::evaluate):
+ (KJS::ReadModifyResolveNode::optimizeVariableAccess):
+ (KJS::AssignResolveNode::optimizeVariableAccess):
+ (KJS::AssignLocalVarNode::evaluate):
+ (KJS::AssignResolveNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::PostDecResolveNode::):
+ (KJS::PostDecResolveNode::precedence):
+ (KJS::PostDecLocalVarNode::):
+ (KJS::PostfixBracketNode::):
+ (KJS::PostfixBracketNode::precedence):
+ (KJS::PostIncBracketNode::):
+ (KJS::PostIncBracketNode::isIncrement):
+ (KJS::PostDecBracketNode::):
+ (KJS::PostDecBracketNode::isIncrement):
+ (KJS::PostfixDotNode::):
+ (KJS::PostfixDotNode::precedence):
+ (KJS::PostIncDotNode::):
+ (KJS::PostIncDotNode::isIncrement):
+ (KJS::PostDecDotNode::):
+ (KJS::PreIncResolveNode::):
+ (KJS::PreDecResolveNode::):
+ (KJS::PreDecResolveNode::precedence):
+ (KJS::PreDecLocalVarNode::):
+ (KJS::PrefixBracketNode::):
+ (KJS::PrefixBracketNode::precedence):
+ (KJS::PreIncBracketNode::):
+ (KJS::PreIncBracketNode::isIncrement):
+ (KJS::PreDecBracketNode::):
+ (KJS::PreDecBracketNode::isIncrement):
+ (KJS::PrefixDotNode::):
+ (KJS::PrefixDotNode::precedence):
+ (KJS::PreIncDotNode::):
+ (KJS::PreIncDotNode::isIncrement):
+ (KJS::PreDecDotNode::):
+ (KJS::ReadModifyResolveNode::):
+ (KJS::ReadModifyLocalVarNode::):
+ (KJS::AssignResolveNode::):
+ (KJS::AssignResolveNode::precedence):
+ * kjs/nodes2string.cpp:
+ (KJS::PostIncResolveNode::streamTo):
+ (KJS::PostDecResolveNode::streamTo):
+ (KJS::PostfixBracketNode::streamTo):
+ (KJS::PostfixDotNode::streamTo):
+ (KJS::PreIncResolveNode::streamTo):
+ (KJS::PreDecResolveNode::streamTo):
+ (KJS::ReadModifyResolveNode::streamTo):
+ (KJS::AssignResolveNode::streamTo):
+
2007-10-29 Maciej Stachowiak <mjs@apple.com>
Not reviewed, build fix.
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
- compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 0867D691FE84028FC02AAC07 /* JavaScriptCore */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = "";
- projectRoot = "";
targets = (
932F5BE30822A1C700736975 /* All */,
932F5B3E0822A1C700736975 /* JavaScriptCore */,
if (loc->isResolveNode()) {
ResolveNode* resolve = static_cast<ResolveNode*>(loc);
- return new AssignResolveNode(resolve->identifier(), op, expr);
+ if (op == OpEqual)
+ return new AssignResolveNode(resolve->identifier(), expr);
+ else
+ return new ReadModifyResolveNode(resolve->identifier(), op, expr);
}
if (loc->isBracketAccessorNode()) {
BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
if (expr->isResolveNode()) {
ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new PrefixResolveNode(resolve->identifier(), op);
+ if (op == OpPlusPlus)
+ return new PreIncResolveNode(resolve->identifier());
+ else
+ return new PreDecResolveNode(resolve->identifier());
}
if (expr->isBracketAccessorNode()) {
BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
- return new PrefixBracketNode(bracket->base(), bracket->subscript(), op);
+ if (op == OpPlusPlus)
+ return new PreIncBracketNode(bracket->base(), bracket->subscript());
+ else
+ return new PreDecBracketNode(bracket->base(), bracket->subscript());
}
ASSERT(expr->isDotAccessorNode());
DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
- return new PrefixDotNode(dot->base(), dot->identifier(), op);
+ if (op == OpPlusPlus)
+ return new PreIncDotNode(dot->base(), dot->identifier());
+ return new PreDecDotNode(dot->base(), dot->identifier());
}
static Node* makePostfixNode(Node* expr, Operator op)
if (expr->isResolveNode()) {
ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new PostfixResolveNode(resolve->identifier(), op);
+ if (op == OpPlusPlus)
+ return new PostIncResolveNode(resolve->identifier());
+ else
+ return new PostDecResolveNode(resolve->identifier());
}
if (expr->isBracketAccessorNode()) {
BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
- return new PostfixBracketNode(bracket->base(), bracket->subscript(), op);
+ if (op == OpPlusPlus)
+ return new PostIncBracketNode(bracket->base(), bracket->subscript());
+ else
+ return new PostDecBracketNode(bracket->base(), bracket->subscript());
}
ASSERT(expr->isDotAccessorNode());
DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
- return new PostfixDotNode(dot->base(), dot->identifier(), op);
+
+ if (op == OpPlusPlus)
+ return new PostIncDotNode(dot->base(), dot->identifier());
+ return new PostDecDotNode(dot->base(), dot->identifier());
}
static Node* makeFunctionCallNode(Node* func, ArgumentsNode* args)
// ------------------------------ PostfixResolveNode ----------------------------------
-void PostfixResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
+// Increment
+void PostIncResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
{
size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
if (index != missingSymbolMarker())
- new (this) LocalVarPostfixNode(index);
+ new (this) PostIncLocalVarNode(index);
}
-JSValue *PostfixResolveNode::evaluate(ExecState *exec)
+JSValue *PostIncResolveNode::evaluate(ExecState *exec)
{
// Check for missed optimization opportunity.
ASSERT(!canSkipLookup(exec, m_ident));
JSValue *v = slot.getValue(exec, base, m_ident);
double n = v->toNumber(exec);
-
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- base->put(exec, m_ident, jsNumber(newValue));
-
+ base->put(exec, m_ident, jsNumber(n + 1));
+ return jsNumber(n);
+ }
+
+ ++iter;
+ } while (iter != end);
+
+ return throwUndefinedVariableError(exec, m_ident);
+}
+
+JSValue* PostIncLocalVarNode::evaluate(ExecState* exec)
+{
+ ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
+ ASSERT(variableObject->isActivation());
+ ASSERT(variableObject == exec->scopeChain().top());
+
+ JSValue** slot = &variableObject->localStorage()[index].value;
+ double n = (*slot)->toNumber(exec);
+ *slot = jsNumber(n + 1);
+ return jsNumber(n);
+}
+
+
+// Decrement
+void PostDecResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
+{
+ size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
+ if (index != missingSymbolMarker())
+ new (this) PostDecLocalVarNode(index);
+}
+
+JSValue *PostDecResolveNode::evaluate(ExecState *exec)
+{
+ // Check for missed optimization opportunity.
+ ASSERT(!canSkipLookup(exec, m_ident));
+
+ const ScopeChain& chain = exec->scopeChain();
+ ScopeChainIterator iter = chain.begin();
+ ScopeChainIterator end = chain.end();
+
+ // we must always have something in the scope chain
+ ASSERT(iter != end);
+
+ PropertySlot slot;
+ JSObject *base;
+ do {
+ base = *iter;
+ if (base->getPropertySlot(exec, m_ident, slot)) {
+ JSValue *v = slot.getValue(exec, base, m_ident);
+
+ double n = v->toNumber(exec);
+ base->put(exec, m_ident, jsNumber(n - 1));
return jsNumber(n);
}
return throwUndefinedVariableError(exec, m_ident);
}
-JSValue* LocalVarPostfixNode::evaluate(ExecState* exec)
+JSValue* PostDecLocalVarNode::evaluate(ExecState* exec)
{
ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
ASSERT(variableObject->isActivation());
JSValue** slot = &variableObject->localStorage()[index].value;
double n = (*slot)->toNumber(exec);
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- *slot = jsNumber(newValue);
+ *slot = jsNumber(n - 1);
return jsNumber(n);
}
nodeStack.append(m_base.get());
}
-JSValue *PostfixBracketNode::evaluate(ExecState *exec)
+JSValue *PostIncBracketNode::evaluate(ExecState *exec)
{
JSValue *baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- base->put(exec, propertyIndex, jsNumber(newValue));
+ base->put(exec, propertyIndex, jsNumber(n + 1));
return jsNumber(n);
}
double n = v->toNumber(exec);
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- base->put(exec, propertyName, jsNumber(newValue));
+ base->put(exec, propertyName, jsNumber(n + 1));
+
+ return jsNumber(n);
+}
+
+JSValue *PostDecBracketNode::evaluate(ExecState *exec)
+{
+ JSValue *baseValue = m_base->evaluate(exec);
+ KJS_CHECKEXCEPTIONVALUE
+ JSValue *subscript = m_subscript->evaluate(exec);
+ KJS_CHECKEXCEPTIONVALUE
+
+ JSObject *base = baseValue->toObject(exec);
+
+ uint32_t propertyIndex;
+ if (subscript->getUInt32(propertyIndex)) {
+ PropertySlot slot;
+ JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
+ KJS_CHECKEXCEPTIONVALUE
+
+ double n = v->toNumber(exec);
+
+ base->put(exec, propertyIndex, jsNumber(n - 1));
+
+ return jsNumber(n);
+ }
+
+ Identifier propertyName(subscript->toString(exec));
+ PropertySlot slot;
+ JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
+ KJS_CHECKEXCEPTIONVALUE
+
+ double n = v->toNumber(exec);
+
+ base->put(exec, propertyName, jsNumber(n - 1));
return jsNumber(n);
}
nodeStack.append(m_base.get());
}
-JSValue *PostfixDotNode::evaluate(ExecState *exec)
+JSValue *PostIncDotNode::evaluate(ExecState *exec)
{
JSValue *baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- base->put(exec, m_ident, jsNumber(newValue));
+ base->put(exec, m_ident, jsNumber(n + 1));
+
+ return jsNumber(n);
+}
+
+JSValue *PostDecDotNode::evaluate(ExecState *exec)
+{
+ JSValue *baseValue = m_base->evaluate(exec);
+ KJS_CHECKEXCEPTIONVALUE
+ JSObject *base = baseValue->toObject(exec);
+
+ PropertySlot slot;
+ JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
+ KJS_CHECKEXCEPTIONVALUE
+
+ double n = v->toNumber(exec);
+
+ base->put(exec, m_ident, jsNumber(n - 1));
return jsNumber(n);
}
// ------------------------------ PrefixResolveNode ----------------------------------
-void PrefixResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
+void PreIncResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
{
size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
if (index != missingSymbolMarker())
- new (this) LocalVarPrefixNode(index);
+ new (this) PreIncLocalVarNode(index);
}
-JSValue* LocalVarPrefixNode::evaluate(ExecState* exec)
+JSValue* PreIncLocalVarNode::evaluate(ExecState* exec)
{
ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
ASSERT(variableObject->isActivation());
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);
+ JSValue* n2 = jsNumber(n + 1);
variableObject->localStorage()[m_index].value = n2;
return n2;
}
-JSValue *PrefixResolveNode::evaluate(ExecState *exec)
+JSValue *PreIncResolveNode::evaluate(ExecState *exec)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
JSValue *v = slot.getValue(exec, base, m_ident);
double n = v->toNumber(exec);
-
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- JSValue *n2 = jsNumber(newValue);
+ JSValue *n2 = jsNumber(n + 1);
+ base->put(exec, m_ident, n2);
+
+ return n2;
+ }
+
+ ++iter;
+ } while (iter != end);
+
+ return throwUndefinedVariableError(exec, m_ident);
+}
+
+void PreDecResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
+{
+ size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
+ if (index != missingSymbolMarker())
+ new (this) PreDecLocalVarNode(index);
+}
+
+JSValue* PreDecLocalVarNode::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);
+ JSValue* n2 = jsNumber(n - 1);
+ variableObject->localStorage()[m_index].value = n2;
+ return n2;
+}
+
+JSValue *PreDecResolveNode::evaluate(ExecState *exec)
+{
+ const ScopeChain& chain = exec->scopeChain();
+ ScopeChainIterator iter = chain.begin();
+ ScopeChainIterator end = chain.end();
+
+ // we must always have something in the scope chain
+ ASSERT(iter != end);
+
+ PropertySlot slot;
+ JSObject *base;
+ do {
+ base = *iter;
+ if (base->getPropertySlot(exec, m_ident, slot)) {
+ JSValue *v = slot.getValue(exec, base, m_ident);
+
+ double n = v->toNumber(exec);
+ JSValue *n2 = jsNumber(n - 1);
base->put(exec, m_ident, n2);
return n2;
nodeStack.append(m_base.get());
}
-JSValue *PrefixBracketNode::evaluate(ExecState *exec)
+JSValue *PreIncBracketNode::evaluate(ExecState *exec)
{
JSValue *baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
- double n = v->toNumber(exec);
+ JSValue *n2 = jsNumber(v->toNumber(exec) + 1);
+ base->put(exec, propertyIndex, n2);
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- JSValue *n2 = jsNumber(newValue);
+ return n2;
+ }
+
+ Identifier propertyName(subscript->toString(exec));
+ PropertySlot slot;
+ JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
+ KJS_CHECKEXCEPTIONVALUE
+
+ JSValue *n2 = jsNumber(v->toNumber(exec) + 1);
+ base->put(exec, propertyName, n2);
+
+ return n2;
+}
+
+JSValue *PreDecBracketNode::evaluate(ExecState *exec)
+{
+ JSValue *baseValue = m_base->evaluate(exec);
+ KJS_CHECKEXCEPTIONVALUE
+ JSValue *subscript = m_subscript->evaluate(exec);
+ KJS_CHECKEXCEPTIONVALUE
+
+ JSObject *base = baseValue->toObject(exec);
+
+ uint32_t propertyIndex;
+ if (subscript->getUInt32(propertyIndex)) {
+ PropertySlot slot;
+ JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
+ KJS_CHECKEXCEPTIONVALUE
+
+ JSValue *n2 = jsNumber(v->toNumber(exec) - 1);
base->put(exec, propertyIndex, n2);
return n2;
JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
- double n = v->toNumber(exec);
-
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- JSValue *n2 = jsNumber(newValue);
+ JSValue *n2 = jsNumber(v->toNumber(exec) - 1);
base->put(exec, propertyName, n2);
return n2;
nodeStack.append(m_base.get());
}
-JSValue *PrefixDotNode::evaluate(ExecState *exec)
+JSValue *PreIncDotNode::evaluate(ExecState *exec)
{
JSValue *baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
-
- double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
- JSValue *n2 = jsNumber(newValue);
+ JSValue *n2 = jsNumber(n + 1);
+ base->put(exec, m_ident, n2);
+
+ return n2;
+}
+
+JSValue *PreDecDotNode::evaluate(ExecState *exec)
+{
+ JSValue *baseValue = m_base->evaluate(exec);
+ KJS_CHECKEXCEPTIONVALUE
+ JSObject *base = baseValue->toObject(exec);
+
+ PropertySlot slot;
+ JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
+ KJS_CHECKEXCEPTIONVALUE
+
+ double n = v->toNumber(exec);
+ JSValue *n2 = jsNumber(n - 1);
base->put(exec, m_ident, n2);
return n2;
return v;
}
-// ------------------------------ AssignResolveNode -----------------------------------
+// ------------------------------ ReadModifyResolveNode -----------------------------------
+
+void ReadModifyResolveNode::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) ReadModifyLocalVarNode(index);
+}
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) LocalVarAssignNode(index);
+ new (this) AssignLocalVarNode(index);
}
-JSValue* LocalVarAssignNode::evaluate(ExecState* exec)
+JSValue* ReadModifyLocalVarNode::evaluate(ExecState* exec)
{
ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
ASSERT(variableObject->isActivation());
return v;
}
-JSValue *AssignResolveNode::evaluate(ExecState *exec)
+JSValue* AssignLocalVarNode::evaluate(ExecState* exec)
+{
+ ActivationImp* variableObject = static_cast<ActivationImp*>(exec->variableObject());
+ ASSERT(variableObject->isActivation());
+ ASSERT(variableObject == exec->scopeChain().top());
+ JSValue* v = m_right->evaluate(exec);
+
+ KJS_CHECKEXCEPTIONVALUE
+
+ variableObject->localStorage()[m_index].value = v;
+
+ return v;
+}
+
+JSValue *ReadModifyResolveNode::evaluate(ExecState *exec)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
return v;
}
+JSValue *AssignResolveNode::evaluate(ExecState *exec)
+{
+ const ScopeChain& chain = exec->scopeChain();
+ ScopeChainIterator iter = chain.begin();
+ ScopeChainIterator end = chain.end();
+
+ // we must always have something in the scope chain
+ ASSERT(iter != end);
+
+ PropertySlot slot;
+ JSObject *base;
+ do {
+ base = *iter;
+ if (base->getPropertySlot(exec, m_ident, slot))
+ goto found;
+
+ ++iter;
+ } while (iter != end);
+
+ found:
+ JSValue *v = m_right->evaluate(exec);
+
+ KJS_CHECKEXCEPTIONVALUE
+
+ base->put(exec, m_ident, v);
+ return v;
+}
+
// ------------------------------ AssignDotNode -----------------------------------
void AssignDotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
RefPtr<ArgumentsNode> args;
};
- class PostfixResolveNode : public Node {
+ class PostIncResolveNode : public Node {
public:
- PostfixResolveNode(const Identifier& i, Operator o) KJS_FAST_CALL : m_ident(i), m_oper(o) {}
+ PostIncResolveNode(const Identifier& i) KJS_FAST_CALL : m_ident(i) {}
- PostfixResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
+ PostIncResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
: Node(PlacementNewAdopt)
, m_ident(PlacementNewAdopt)
{
protected:
Identifier m_ident;
- Operator m_oper;
size_t index; // Used by LocalVarPostfixNode.
};
- class LocalVarPostfixNode : public PostfixResolveNode {
+ class PostIncLocalVarNode : public PostIncResolveNode {
public:
- LocalVarPostfixNode(size_t i) KJS_FAST_CALL
- : PostfixResolveNode(PlacementNewAdopt)
+ PostIncLocalVarNode(size_t i) KJS_FAST_CALL
+ : PostIncResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
index = i;
JSValue* evaluate(ExecState*) KJS_FAST_CALL;
};
- class PostfixBracketNode : public Node {
+ class PostDecResolveNode : public Node {
public:
- PostfixBracketNode(Node *b, Node *s, Operator o) KJS_FAST_CALL : m_base(b), m_subscript(s), m_oper(o) {}
+ PostDecResolveNode(const Identifier& i) KJS_FAST_CALL : m_ident(i) {}
+
+ PostDecResolveNode(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 PrecPostfix; }
- private:
+
+ protected:
+ Identifier m_ident;
+ size_t index; // Used by LocalVarPostfixNode.
+ };
+
+ class PostDecLocalVarNode : public PostDecResolveNode {
+ public:
+ PostDecLocalVarNode(size_t i) KJS_FAST_CALL
+ : PostDecResolveNode(PlacementNewAdopt)
+ {
+ ASSERT(i != missingSymbolMarker());
+ index = i;
+ }
+
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ };
+
+ class PostfixBracketNode : public Node {
+ public:
+ PostfixBracketNode(Node *b, Node *s) KJS_FAST_CALL : m_base(b), m_subscript(s) {}
+ virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
+ virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+ virtual Precedence precedence() const { return PrecPostfix; }
+ protected:
+ virtual bool isIncrement() const = 0;
RefPtr<Node> m_base;
RefPtr<Node> m_subscript;
- Operator m_oper;
+ };
+
+ class PostIncBracketNode : public PostfixBracketNode {
+ public:
+ PostIncBracketNode(Node *b, Node *s) KJS_FAST_CALL : PostfixBracketNode(b, s) {}
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ protected:
+ virtual bool isIncrement() const { return true; }
+ };
+
+ class PostDecBracketNode : public PostfixBracketNode {
+ public:
+ PostDecBracketNode(Node *b, Node *s) KJS_FAST_CALL : PostfixBracketNode(b, s) {}
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ protected:
+ virtual bool isIncrement() const { return false; }
};
class PostfixDotNode : public Node {
public:
- PostfixDotNode(Node *b, const Identifier& i, Operator o) KJS_FAST_CALL : m_base(b), m_ident(i), m_oper(o) {}
+ PostfixDotNode(Node *b, const Identifier& i) KJS_FAST_CALL : m_base(b), m_ident(i) {}
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 PrecPostfix; }
- private:
+ protected:
+ virtual bool isIncrement() const = 0;
RefPtr<Node> m_base;
Identifier m_ident;
- Operator m_oper;
+ };
+
+ class PostIncDotNode : public PostfixDotNode {
+ public:
+ PostIncDotNode(Node *b, const Identifier& i) KJS_FAST_CALL : PostfixDotNode(b, i) {}
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ protected:
+ virtual bool isIncrement() const { return true; }
+ };
+
+ class PostDecDotNode : public PostfixDotNode {
+ public:
+ PostDecDotNode(Node *b, const Identifier& i) KJS_FAST_CALL : PostfixDotNode(b, i) {}
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ protected:
+ virtual bool isIncrement() const { return false; }
};
class PostfixErrorNode : public Node {
RefPtr<Node> m_expr;
};
- class PrefixResolveNode : public Node {
+ class PreIncResolveNode : public Node {
public:
- PrefixResolveNode(const Identifier &s, Operator o) KJS_FAST_CALL
+ PreIncResolveNode(const Identifier &s) KJS_FAST_CALL
: m_ident(s)
- , m_oper(o)
{
}
- PrefixResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
+ PreIncResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
: Node(PlacementNewAdopt)
, m_ident(PlacementNewAdopt)
{
protected:
Identifier m_ident;
- Operator m_oper;
size_t m_index; // Used by LocalVarPrefixNode.
};
- class LocalVarPrefixNode : public PrefixResolveNode {
+ class PreIncLocalVarNode : public PreIncResolveNode {
public:
- LocalVarPrefixNode(size_t i) KJS_FAST_CALL
- : PrefixResolveNode(PlacementNewAdopt)
+ PreIncLocalVarNode(size_t i) KJS_FAST_CALL
+ : PreIncResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
JSValue* evaluate(ExecState*) KJS_FAST_CALL;
};
+
+ class PreDecResolveNode : public Node {
+ public:
+ PreDecResolveNode(const Identifier &s) KJS_FAST_CALL
+ : m_ident(s)
+ {
+ }
+
+ PreDecResolveNode(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; }
+ protected:
+ Identifier m_ident;
+ size_t m_index; // Used by LocalVarPrefixNode.
+ };
+
+ class PreDecLocalVarNode : public PreDecResolveNode {
+ public:
+ PreDecLocalVarNode(size_t i) KJS_FAST_CALL
+ : PreDecResolveNode(PlacementNewAdopt)
+ {
+ ASSERT(i != missingSymbolMarker());
+ m_index = i;
+ }
+
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ };
+
class PrefixBracketNode : public Node {
public:
- PrefixBracketNode(Node *b, Node *s, Operator o) KJS_FAST_CALL : m_base(b), m_subscript(s), m_oper(o) {}
+ PrefixBracketNode(Node *b, Node *s) KJS_FAST_CALL : m_base(b), m_subscript(s) {}
+
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:
+ virtual bool isIncrement() const = 0;
RefPtr<Node> m_base;
RefPtr<Node> m_subscript;
- Operator m_oper;
+ };
+
+ class PreIncBracketNode : public PrefixBracketNode {
+ public:
+ PreIncBracketNode(Node *b, Node *s) KJS_FAST_CALL : PrefixBracketNode(b, s) {}
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ protected:
+ bool isIncrement() const { return true; }
+ };
+
+ class PreDecBracketNode : public PrefixBracketNode {
+ public:
+ PreDecBracketNode(Node *b, Node *s) KJS_FAST_CALL : PrefixBracketNode(b, s) {}
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ protected:
+ bool isIncrement() const { return false; }
};
class PrefixDotNode : public Node {
public:
- PrefixDotNode(Node *b, const Identifier& i, Operator o) KJS_FAST_CALL : m_base(b), m_ident(i), m_oper(o) {}
+ PrefixDotNode(Node *b, const Identifier& i) KJS_FAST_CALL : m_base(b), m_ident(i) {}
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:
+ virtual Precedence precedence() const { return PrecPostfix; }
+ protected:
+ virtual bool isIncrement() const = 0;
RefPtr<Node> m_base;
Identifier m_ident;
- Operator m_oper;
+ };
+
+ class PreIncDotNode : public PrefixDotNode {
+ public:
+ PreIncDotNode(Node *b, const Identifier& i) KJS_FAST_CALL : PrefixDotNode(b, i) {}
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ protected:
+ virtual bool isIncrement() const { return true; }
+ };
+
+ class PreDecDotNode : public PrefixDotNode {
+ public:
+ PreDecDotNode(Node *b, const Identifier& i) KJS_FAST_CALL : PrefixDotNode(b, i) {}
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ protected:
+ virtual bool isIncrement() const { return false; }
};
class PrefixErrorNode : public Node {
RefPtr<Node> expr2;
};
- class AssignResolveNode : public Node {
+ class ReadModifyResolveNode : public Node {
public:
- AssignResolveNode(const Identifier &ident, Operator oper, Node *right) KJS_FAST_CALL
+ ReadModifyResolveNode(const Identifier &ident, Operator oper, Node *right) KJS_FAST_CALL
: m_ident(ident)
, m_oper(oper)
, m_right(right)
{
}
- AssignResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
+ ReadModifyResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
: Node(PlacementNewAdopt)
, m_ident(PlacementNewAdopt)
, m_right(PlacementNewAdopt)
Identifier m_ident;
Operator m_oper;
RefPtr<Node> m_right;
- size_t m_index; // Used by LocalVarAssignNode.
+ size_t m_index; // Used by ReadModifyLocalVarNode.
+ };
+
+ class ReadModifyLocalVarNode : public ReadModifyResolveNode {
+ public:
+ ReadModifyLocalVarNode(size_t i) KJS_FAST_CALL
+ : ReadModifyResolveNode(PlacementNewAdopt)
+ {
+ ASSERT(i != missingSymbolMarker());
+ m_index = i;
+ }
+
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ };
+
+ class AssignResolveNode : public Node {
+ public:
+ AssignResolveNode(const Identifier &ident, Node *right) KJS_FAST_CALL
+ : m_ident(ident)
+ , m_right(right)
+ {
+ }
+
+ AssignResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
+ : Node(PlacementNewAdopt)
+ , m_ident(PlacementNewAdopt)
+ , 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;
+ virtual Precedence precedence() const { return PrecAssignment; }
+ protected:
+ Identifier m_ident;
+ RefPtr<Node> m_right;
+ size_t m_index; // Used by ReadModifyLocalVarNode.
};
- class LocalVarAssignNode : public AssignResolveNode {
+ class AssignLocalVarNode : public AssignResolveNode {
public:
- LocalVarAssignNode(size_t i) KJS_FAST_CALL
+ AssignLocalVarNode(size_t i) KJS_FAST_CALL
: AssignResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
s << DotExpr << PrecCall << base << "." << ident << args;
}
-void PostfixResolveNode::streamTo(SourceStream& s) const
+void PostIncResolveNode::streamTo(SourceStream& s) const
{
- s << m_ident;
- if (m_oper == OpPlusPlus)
- s << "++";
- else
- s << "--";
+ s << m_ident << "++";
+}
+
+void PostDecResolveNode::streamTo(SourceStream& s) const
+{
+ s << m_ident << "--";
}
void PostfixBracketNode::streamTo(SourceStream& s) const
{
s << PrecCall << m_base << "[" << m_subscript << "]";
- if (m_oper == OpPlusPlus)
+ if (isIncrement())
s << "++";
else
s << "--";
void PostfixDotNode::streamTo(SourceStream& s) const
{
s << DotExpr << PrecCall << m_base << "." << m_ident;
- if (m_oper == OpPlusPlus)
+ if (isIncrement())
s << "++";
else
s << "--";
s << "typeof " << m_ident;
}
-void PrefixResolveNode::streamTo(SourceStream& s) const
+void PreIncResolveNode::streamTo(SourceStream& s) const
{
- if (m_oper == OpPlusPlus)
- s << "++";
- else
- s << "--";
- s << m_ident;
+ s << "++" << m_ident;
+}
+
+void PreDecResolveNode::streamTo(SourceStream& s) const
+{
+ s << "--" << m_ident;
}
void PrefixBracketNode::streamTo(SourceStream& s) const
{
- if (m_oper == OpPlusPlus)
+ if (isIncrement())
s << "++";
else
s << "--";
void PrefixDotNode::streamTo(SourceStream& s) const
{
- if (m_oper == OpPlusPlus)
+ if (isIncrement())
s << "++";
else
s << "--";
<< " : " << PrecAssignment << expr2;
}
-void AssignResolveNode::streamTo(SourceStream& s) const
+void ReadModifyResolveNode::streamTo(SourceStream& s) const
{
s << m_ident << ' ' << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
}
+void AssignResolveNode::streamTo(SourceStream& s) const
+{
+ s << m_ident << " = " << PrecAssignment << m_right;
+}
+
void AssignBracketNode::streamTo(SourceStream& s) const
{
s << PrecCall << m_base << '[' << m_subscript << "] "