Index: VM/CodeGenerator.h =================================================================== --- VM/CodeGenerator.h (revision 33029) +++ VM/CodeGenerator.h (working copy) @@ -145,6 +145,17 @@ namespace KJS { return emitNode(0, n); } + RegisterID* emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments) + { + if (n->isResolveNode() && (m_codeBlock->usesEval || m_codeBlock->needsClosure || rightHasAssignments)) { + RefPtr dst = newTemporary(); + emitNode(dst.get(), n); + return dst.get(); + } + + return emitNode(n); + } + RegisterID* emitLoad(RegisterID* dst, bool); RegisterID* emitLoad(RegisterID* dst, double); RegisterID* emitLoad(RegisterID* dst, JSValue*); Index: kjs/NodeInfo.h =================================================================== --- kjs/NodeInfo.h (revision 33029) +++ kjs/NodeInfo.h (working copy) @@ -30,6 +30,7 @@ namespace KJS { const FeatureInfo NoFeatures = 0; const FeatureInfo EvalFeature = 1 << 0; const FeatureInfo ClosureFeature = 1 << 1; + const FeatureInfo AssignFeature = 1 << 2; template struct NodeFeatureInfo { T m_node; Index: kjs/grammar.y =================================================================== --- kjs/grammar.y (revision 33029) +++ kjs/grammar.y (working copy) @@ -63,7 +63,7 @@ using namespace std; static AddNode* makeAddNode(ExpressionNode*, ExpressionNode*); static LessNode* makeLessNode(ExpressionNode*, ExpressionNode*); -static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr); +static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr, bool exprHasAssignments); static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator); static ExpressionNode* makePostfixNode(ExpressionNode* expr, Operator); static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceRange&); @@ -97,14 +97,14 @@ template NodeDeclarationInf ParserRefCountedData* funcDecls, FeatureInfo info) { - ASSERT((info & ~(EvalFeature | ClosureFeature)) == 0); + ASSERT((info & ~(EvalFeature | ClosureFeature | AssignFeature)) == 0); NodeDeclarationInfo result = {node, varDecls, funcDecls, info}; return result; } template NodeFeatureInfo createNodeFeatureInfo(T node, FeatureInfo info) { - ASSERT((info & ~(EvalFeature | ClosureFeature)) == 0); + ASSERT((info & ~(EvalFeature | ClosureFeature | AssignFeature)) == 0); NodeFeatureInfo result = {node, info}; return result; } @@ -667,19 +667,19 @@ ConditionalExprNoBF: AssignmentExpr: ConditionalExpr | LeftHandSideExpr AssignmentOperator AssignmentExpr - { $$ = createNodeFeatureInfo(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); } + { $$ = createNodeFeatureInfo(makeAssignNode($1.m_node, $2, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); } ; AssignmentExprNoIn: ConditionalExprNoIn | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn - { $$ = createNodeFeatureInfo(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); } + { $$ = createNodeFeatureInfo(makeAssignNode($1.m_node, $2, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); } ; AssignmentExprNoBF: ConditionalExprNoBF | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr - { $$ = createNodeFeatureInfo(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); } + { $$ = createNodeFeatureInfo(makeAssignNode($1.m_node, $2, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); } ; AssignmentOperator: @@ -1125,7 +1125,7 @@ static LessNode* makeLessNode(Expression return new LessNode(left, right); } -static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr) +static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr, bool exprHasAssignments) { if (!loc->isLocation()) return new AssignErrorNode(loc, op, expr); @@ -1140,15 +1140,15 @@ static ExpressionNode* makeAssignNode(Ex if (loc->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast(loc); if (op == OpEqual) - return new AssignBracketNode(bracket->base(), bracket->subscript(), expr); + return new AssignBracketNode(bracket->base(), bracket->subscript(), expr, exprHasAssignments); else - return new ReadModifyBracketNode(bracket->base(), bracket->subscript(), op, expr); + return new ReadModifyBracketNode(bracket->base(), bracket->subscript(), op, expr, exprHasAssignments); } ASSERT(loc->isDotAccessorNode()); DotAccessorNode* dot = static_cast(loc); if (op == OpEqual) - return new AssignDotNode(dot->base(), dot->identifier(), expr); - return new ReadModifyDotNode(dot->base(), dot->identifier(), op, expr); + return new AssignDotNode(dot->base(), dot->identifier(), expr, exprHasAssignments); + return new ReadModifyDotNode(dot->base(), dot->identifier(), op, expr, exprHasAssignments); } static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator op) Index: kjs/nodes.cpp =================================================================== --- kjs/nodes.cpp (revision 33029) +++ kjs/nodes.cpp (working copy) @@ -4344,7 +4344,7 @@ found: RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) { - RefPtr base = generator.emitNode(m_base.get()); + RefPtr base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments); RegisterID* value = generator.emitNode(dst, m_right.get()); return generator.emitPutById(base.get(), m_ident, value); } @@ -4371,7 +4371,7 @@ JSValue* AssignDotNode::evaluate(OldInte RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) { - RefPtr base = generator.emitNode(m_base.get()); + RefPtr base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments); // FIXME: should not write temp value to dst if dst is a local! RefPtr value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); @@ -4424,8 +4424,8 @@ JSValue* AssignErrorNode::evaluate(OldIn RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst) { - RefPtr base = generator.emitNode(m_base.get()); - RefPtr property = generator.emitNode(m_subscript.get()); + RefPtr base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments); + RefPtr property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments); RegisterID* value = generator.emitNode(dst, m_right.get()); return generator.emitPutByVal(base.get(), property.get(), value); } @@ -4465,8 +4465,8 @@ JSValue* AssignBracketNode::evaluate(Old RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst) { - RefPtr base = generator.emitNode(m_base.get()); - RefPtr property = generator.emitNode(m_subscript.get()); + RefPtr base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments); + RefPtr property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments); RefPtr value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); RegisterID* change = generator.emitNode(m_right.get()); Index: kjs/nodes.h =================================================================== --- kjs/nodes.h (revision 33029) +++ kjs/nodes.h (working copy) @@ -2404,11 +2404,12 @@ namespace KJS { class ReadModifyBracketNode : public ExpressionNode { public: - ReadModifyBracketNode(ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right) KJS_FAST_CALL + ReadModifyBracketNode(ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL : m_base(base) , m_subscript(subscript) - , m_operator(oper) , m_right(right) + , m_operator(oper) + , m_rightHasAssignments(rightHasAssignments) { } @@ -2422,16 +2423,18 @@ namespace KJS { protected: RefPtr m_base; RefPtr m_subscript; - Operator m_operator; RefPtr m_right; + Operator m_operator : 31; + bool m_rightHasAssignments : 1; }; class AssignBracketNode : public ExpressionNode { public: - AssignBracketNode(ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right) KJS_FAST_CALL + AssignBracketNode(ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL : m_base(base) , m_subscript(subscript) , m_right(right) + , m_rightHasAssignments(rightHasAssignments) { } @@ -2446,14 +2449,16 @@ namespace KJS { RefPtr m_base; RefPtr m_subscript; RefPtr m_right; + bool m_rightHasAssignments; }; class AssignDotNode : public ExpressionNode { public: - AssignDotNode(ExpressionNode* base, const Identifier& ident, ExpressionNode* right) KJS_FAST_CALL + AssignDotNode(ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL : m_base(base) , m_ident(ident) , m_right(right) + , m_rightHasAssignments(rightHasAssignments) { } @@ -2467,15 +2472,17 @@ namespace KJS { RefPtr m_base; Identifier m_ident; RefPtr m_right; + bool m_rightHasAssignments; }; class ReadModifyDotNode : public ExpressionNode { public: - ReadModifyDotNode(ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right) KJS_FAST_CALL + ReadModifyDotNode(ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL : m_base(base) , m_ident(ident) - , m_operator(oper) , m_right(right) + , m_operator(oper) + , m_rightHasAssignments(rightHasAssignments) { } @@ -2489,8 +2496,9 @@ namespace KJS { protected: RefPtr m_base; Identifier m_ident; - Operator m_operator; RefPtr m_right; + Operator m_operator : 31; + bool m_rightHasAssignments : 1; }; class AssignErrorNode : public ExpressionNode {