2008-06-15 Cameron Zwarich <cwzwarich@uwaterloo.ca>
authorcwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 15 Jun 2008 09:30:56 +0000 (09:30 +0000)
committercwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 15 Jun 2008 09:30:56 +0000 (09:30 +0000)
        Reviewed by Maciej.

        Bug 19484: More instructions needs to use temporary registers
        <https://bugs.webkit.org/show_bug.cgi?id=19484>

        Fix codegen for all binary operations so that temporaries are used if
        necessary. This was done by making BinaryOpNode and ReverseBinaryOpNode
        subclasses of ExpressionNode, and eliminating the custom emitCode()
        methods for the individual node classes.

        This only adds 3 new instructions to SunSpider code, and there is no
        difference in SunSpider execution time.

        JavaScriptCore:

        * VM/CodeGenerator.cpp:
        (KJS::CodeGenerator::emitBitNot):
        (KJS::CodeGenerator::emitBinaryOp):
        * VM/CodeGenerator.h:
        * kjs/grammar.y:
        * kjs/nodes.cpp:
        (KJS::PreIncResolveNode::emitCode):
        (KJS::PreDecResolveNode::emitCode):
        (KJS::BinaryOpNode::emitCode):
        (KJS::ReverseBinaryOpNode::emitCode):
        (KJS::emitReadModifyAssignment):
        (KJS::CaseBlockNode::emitCodeForBlock):
        * kjs/nodes.h:
        (KJS::BinaryOpNode::BinaryOpNode):
        (KJS::ReverseBinaryOpNode::ReverseBinaryOpNode):
        (KJS::MultNode::):
        (KJS::DivNode::):
        (KJS::DivNode::precedence):
        (KJS::ModNode::):
        (KJS::ModNode::precedence):
        (KJS::AddNode::):
        (KJS::AddNode::precedence):
        (KJS::SubNode::):
        (KJS::SubNode::precedence):
        (KJS::LeftShiftNode::):
        (KJS::LeftShiftNode::precedence):
        (KJS::RightShiftNode::):
        (KJS::RightShiftNode::precedence):
        (KJS::UnsignedRightShiftNode::):
        (KJS::UnsignedRightShiftNode::precedence):
        (KJS::LessNode::):
        (KJS::LessNode::precedence):
        (KJS::GreaterNode::):
        (KJS::GreaterNode::precedence):
        (KJS::LessEqNode::):
        (KJS::LessEqNode::precedence):
        (KJS::GreaterEqNode::):
        (KJS::GreaterEqNode::precedence):
        (KJS::InstanceOfNode::):
        (KJS::InstanceOfNode::precedence):
        (KJS::InNode::):
        (KJS::InNode::precedence):
        (KJS::EqualNode::):
        (KJS::EqualNode::precedence):
        (KJS::NotEqualNode::):
        (KJS::NotEqualNode::precedence):
        (KJS::StrictEqualNode::):
        (KJS::StrictEqualNode::precedence):
        (KJS::NotStrictEqualNode::):
        (KJS::NotStrictEqualNode::precedence):
        (KJS::BitAndNode::):
        (KJS::BitAndNode::precedence):
        (KJS::BitOrNode::):
        (KJS::BitOrNode::precedence):
        (KJS::BitXOrNode::):
        (KJS::BitXOrNode::precedence):
        * kjs/nodes2string.cpp:
        (KJS::LessNode::streamTo):
        (KJS::GreaterNode::streamTo):
        (KJS::LessEqNode::streamTo):
        (KJS::GreaterEqNode::streamTo):
        (KJS::InstanceOfNode::streamTo):
        (KJS::InNode::streamTo):
        (KJS::EqualNode::streamTo):
        (KJS::NotEqualNode::streamTo):
        (KJS::StrictEqualNode::streamTo):
        (KJS::NotStrictEqualNode::streamTo):
        (KJS::BitAndNode::streamTo):
        (KJS::BitXOrNode::streamTo):
        (KJS::BitOrNode::streamTo):

        LayoutTests:

        * fast/js/codegen-temporaries-expected.txt:
        * fast/js/resources/codegen-temporaries.js:

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

JavaScriptCore/ChangeLog
JavaScriptCore/VM/CodeGenerator.cpp
JavaScriptCore/VM/CodeGenerator.h
JavaScriptCore/kjs/grammar.y
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/nodes.h
JavaScriptCore/kjs/nodes2string.cpp
LayoutTests/ChangeLog
LayoutTests/fast/js/codegen-temporaries-expected.txt
LayoutTests/fast/js/resources/codegen-temporaries.js

index aa6429954ef042a763b638d8cdd61b54bdf264d3..44db8959f8467df86a38cd84352ab2fd684b0bd9 100644 (file)
@@ -1,3 +1,89 @@
+2008-06-15  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
+
+        Reviewed by Maciej.
+
+        Bug 19484: More instructions needs to use temporary registers
+        <https://bugs.webkit.org/show_bug.cgi?id=19484>
+
+        Fix codegen for all binary operations so that temporaries are used if
+        necessary. This was done by making BinaryOpNode and ReverseBinaryOpNode
+        subclasses of ExpressionNode, and eliminating the custom emitCode()
+        methods for the individual node classes.
+
+        This only adds 3 new instructions to SunSpider code, and there is no
+        difference in SunSpider execution time.
+
+        * VM/CodeGenerator.cpp:
+        (KJS::CodeGenerator::emitBitNot):
+        (KJS::CodeGenerator::emitBinaryOp):
+        * VM/CodeGenerator.h:
+        * kjs/grammar.y:
+        * kjs/nodes.cpp:
+        (KJS::PreIncResolveNode::emitCode):
+        (KJS::PreDecResolveNode::emitCode):
+        (KJS::BinaryOpNode::emitCode):
+        (KJS::ReverseBinaryOpNode::emitCode):
+        (KJS::emitReadModifyAssignment):
+        (KJS::CaseBlockNode::emitCodeForBlock):
+        * kjs/nodes.h:
+        (KJS::BinaryOpNode::BinaryOpNode):
+        (KJS::ReverseBinaryOpNode::ReverseBinaryOpNode):
+        (KJS::MultNode::):
+        (KJS::DivNode::):
+        (KJS::DivNode::precedence):
+        (KJS::ModNode::):
+        (KJS::ModNode::precedence):
+        (KJS::AddNode::):
+        (KJS::AddNode::precedence):
+        (KJS::SubNode::):
+        (KJS::SubNode::precedence):
+        (KJS::LeftShiftNode::):
+        (KJS::LeftShiftNode::precedence):
+        (KJS::RightShiftNode::):
+        (KJS::RightShiftNode::precedence):
+        (KJS::UnsignedRightShiftNode::):
+        (KJS::UnsignedRightShiftNode::precedence):
+        (KJS::LessNode::):
+        (KJS::LessNode::precedence):
+        (KJS::GreaterNode::):
+        (KJS::GreaterNode::precedence):
+        (KJS::LessEqNode::):
+        (KJS::LessEqNode::precedence):
+        (KJS::GreaterEqNode::):
+        (KJS::GreaterEqNode::precedence):
+        (KJS::InstanceOfNode::):
+        (KJS::InstanceOfNode::precedence):
+        (KJS::InNode::):
+        (KJS::InNode::precedence):
+        (KJS::EqualNode::):
+        (KJS::EqualNode::precedence):
+        (KJS::NotEqualNode::):
+        (KJS::NotEqualNode::precedence):
+        (KJS::StrictEqualNode::):
+        (KJS::StrictEqualNode::precedence):
+        (KJS::NotStrictEqualNode::):
+        (KJS::NotStrictEqualNode::precedence):
+        (KJS::BitAndNode::):
+        (KJS::BitAndNode::precedence):
+        (KJS::BitOrNode::):
+        (KJS::BitOrNode::precedence):
+        (KJS::BitXOrNode::):
+        (KJS::BitXOrNode::precedence):
+        * kjs/nodes2string.cpp:
+        (KJS::LessNode::streamTo):
+        (KJS::GreaterNode::streamTo):
+        (KJS::LessEqNode::streamTo):
+        (KJS::GreaterEqNode::streamTo):
+        (KJS::InstanceOfNode::streamTo):
+        (KJS::InNode::streamTo):
+        (KJS::EqualNode::streamTo):
+        (KJS::NotEqualNode::streamTo):
+        (KJS::StrictEqualNode::streamTo):
+        (KJS::NotStrictEqualNode::streamTo):
+        (KJS::BitAndNode::streamTo):
+        (KJS::BitXOrNode::streamTo):
+        (KJS::BitOrNode::streamTo):
+
 2008-06-14  Darin Adler  <darin@apple.com>
 
         Rubber stamped by Sam.
index 096b619645f3b0b7e979029282f47e9cf07eb8af..2563d9ec6f34cf4f5f075c641a7d811ee1d13820 100644 (file)
@@ -517,60 +517,6 @@ RegisterID* CodeGenerator::emitNot(RegisterID* dst, RegisterID* src)
     return dst;
 }
 
-RegisterID* CodeGenerator::emitEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_eq);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitNotEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_neq);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitStrictEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_stricteq);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitNotStrictEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_nstricteq);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitLess(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_less);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitLessEq(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_lesseq);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
 RegisterID* CodeGenerator::emitPreInc(RegisterID* srcDst)
 {
     emitOpcode(op_pre_inc);
@@ -617,113 +563,23 @@ RegisterID* CodeGenerator::emitNegate(RegisterID* dst, RegisterID* src)
     return dst;
 }
 
-RegisterID* CodeGenerator::emitAdd(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_add);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitMul(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_mul);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitDiv(RegisterID* dst, RegisterID* dividend, RegisterID* divisor)
-{
-    emitOpcode(op_div);
-    instructions().append(dst->index());
-    instructions().append(dividend->index());
-    instructions().append(divisor->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitMod(RegisterID* dst, RegisterID* dividend, RegisterID* divisor)
-{
-    emitOpcode(op_mod);
-    instructions().append(dst->index());
-    instructions().append(dividend->index());
-    instructions().append(divisor->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitSub(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_sub);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitLeftShift(RegisterID* dst, RegisterID* val, RegisterID* shift)
-{
-    emitOpcode(op_lshift);
-    instructions().append(dst->index());
-    instructions().append(val->index());
-    instructions().append(shift->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitRightShift(RegisterID* dst, RegisterID* val, RegisterID* shift)
-{
-    emitOpcode(op_rshift);
-    instructions().append(dst->index());
-    instructions().append(val->index());
-    instructions().append(shift->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitUnsignedRightShift(RegisterID* dst, RegisterID* val, RegisterID* shift)
-{
-    emitOpcode(op_urshift);
-    instructions().append(dst->index());
-    instructions().append(val->index());
-    instructions().append(shift->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitBitAnd(RegisterID* dst, RegisterID* src1, RegisterID* src2)
-{
-    emitOpcode(op_bitand);
-    instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
-    return dst;
-}
-
-RegisterID* CodeGenerator::emitBitXOr(RegisterID* dst, RegisterID* src1, RegisterID* src2)
+RegisterID* CodeGenerator::emitBitNot(RegisterID* dst, RegisterID* src)
 {
-    emitOpcode(op_bitxor);
+    emitOpcode(op_bitnot);
     instructions().append(dst->index());
-    instructions().append(src1->index());
-    instructions().append(src2->index());
+    instructions().append(src->index());
     return dst;
 }
 
-RegisterID* CodeGenerator::emitBitOr(RegisterID* dst, RegisterID* src1, RegisterID* src2)
+RegisterID* CodeGenerator::emitBinaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    emitOpcode(op_bitor);
+    emitOpcode(opcode);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
     return dst;
 }
 
-RegisterID* CodeGenerator::emitBitNot(RegisterID* dst, RegisterID* src)
-{
-    emitOpcode(op_bitnot);
-    instructions().append(dst->index());
-    instructions().append(src->index());
-    return dst;
-}
-
 RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base)
 {
     emitOpcode(op_instanceof);
index 8e2cbc6a6cb378c3b4b9aabbee41108fc898024a..52e77942c2c3651bcc8ad911c13c3acbcedc13d9 100644 (file)
@@ -202,12 +202,7 @@ namespace KJS {
         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
 
         RegisterID* emitNot(RegisterID* dst, RegisterID* src);
-        RegisterID* emitEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitNotEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitStrictEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitNotStrictEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitLess(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitLessEq(RegisterID* dst, RegisterID* src1, RegisterID* src2);
+        RegisterID* emitBitNot(RegisterID* dst, RegisterID* src);
 
         RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src);
         RegisterID* emitNegate(RegisterID* dst, RegisterID* src);
@@ -215,20 +210,8 @@ namespace KJS {
         RegisterID* emitPreDec(RegisterID* srcDst);
         RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
         RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
-        RegisterID* emitAdd(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitMul(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitDiv(RegisterID* dst, RegisterID* dividend, RegisterID* divisor);
-        RegisterID* emitMod(RegisterID* dst, RegisterID* dividend, RegisterID* divisor);
-        RegisterID* emitSub(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-
-        RegisterID* emitLeftShift(RegisterID* dst, RegisterID* val, RegisterID* shift);
-        RegisterID* emitRightShift(RegisterID* dst, RegisterID* val, RegisterID* shift);
-        RegisterID* emitUnsignedRightShift(RegisterID* dst, RegisterID* val, RegisterID* shift);
-
-        RegisterID* emitBitAnd(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitBitXOr(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitBitOr(RegisterID* dst, RegisterID* src1, RegisterID* src2);
-        RegisterID* emitBitNot(RegisterID* dst, RegisterID* src);
+
+        RegisterID* emitBinaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src1, RegisterID* src2);
 
         RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base);
         RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src);
index 68d0f7301bc2ad7acf56f8c7c73a8a154095d441..d8851d2be74a02d5f4f7155b2252c39ce76629d9 100644 (file)
@@ -458,19 +458,19 @@ UnaryExprNoBF:
 
 MultiplicativeExpr:
     UnaryExpr
-  | MultiplicativeExpr '*' UnaryExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new MultNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | MultiplicativeExpr '/' UnaryExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new DivNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | MultiplicativeExpr '%' UnaryExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new ModNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | MultiplicativeExpr '*' UnaryExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new MultNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | MultiplicativeExpr '/' UnaryExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new DivNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | MultiplicativeExpr '%' UnaryExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new ModNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 MultiplicativeExprNoBF:
     UnaryExprNoBF
   | MultiplicativeExprNoBF '*' UnaryExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new MultNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new MultNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | MultiplicativeExprNoBF '/' UnaryExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new DivNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new DivNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | MultiplicativeExprNoBF '%' UnaryExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new ModNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new ModNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 AdditiveExpr:
@@ -489,128 +489,128 @@ AdditiveExprNoBF:
 
 ShiftExpr:
     AdditiveExpr
-  | ShiftExpr LSHIFT AdditiveExpr       { $$ = createNodeFeatureInfo<ExpressionNode*>(new LeftShiftNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | ShiftExpr RSHIFT AdditiveExpr       { $$ = createNodeFeatureInfo<ExpressionNode*>(new RightShiftNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | ShiftExpr URSHIFT AdditiveExpr      { $$ = createNodeFeatureInfo<ExpressionNode*>(new UnsignedRightShiftNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | ShiftExpr LSHIFT AdditiveExpr       { $$ = createNodeFeatureInfo<ExpressionNode*>(new LeftShiftNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | ShiftExpr RSHIFT AdditiveExpr       { $$ = createNodeFeatureInfo<ExpressionNode*>(new RightShiftNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | ShiftExpr URSHIFT AdditiveExpr      { $$ = createNodeFeatureInfo<ExpressionNode*>(new UnsignedRightShiftNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 ShiftExprNoBF:
     AdditiveExprNoBF
-  | ShiftExprNoBF LSHIFT AdditiveExpr   { $$ = createNodeFeatureInfo<ExpressionNode*>(new LeftShiftNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | ShiftExprNoBF RSHIFT AdditiveExpr   { $$ = createNodeFeatureInfo<ExpressionNode*>(new RightShiftNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | ShiftExprNoBF URSHIFT AdditiveExpr  { $$ = createNodeFeatureInfo<ExpressionNode*>(new UnsignedRightShiftNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | ShiftExprNoBF LSHIFT AdditiveExpr   { $$ = createNodeFeatureInfo<ExpressionNode*>(new LeftShiftNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | ShiftExprNoBF RSHIFT AdditiveExpr   { $$ = createNodeFeatureInfo<ExpressionNode*>(new RightShiftNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | ShiftExprNoBF URSHIFT AdditiveExpr  { $$ = createNodeFeatureInfo<ExpressionNode*>(new UnsignedRightShiftNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 RelationalExpr:
     ShiftExpr
-  | RelationalExpr '<' ShiftExpr        { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExpr '>' ShiftExpr        { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExpr LE ShiftExpr         { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessEqNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExpr GE ShiftExpr         { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterEqNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExpr INSTANCEOF ShiftExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(new InstanceOfNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExpr INTOKEN ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new InNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExpr '<' ShiftExpr        { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExpr '>' ShiftExpr        { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExpr LE ShiftExpr         { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessEqNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExpr GE ShiftExpr         { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterEqNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExpr INSTANCEOF ShiftExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(new InstanceOfNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExpr INTOKEN ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new InNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 RelationalExprNoIn:
     ShiftExpr
-  | RelationalExprNoIn '<' ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExprNoIn '>' ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExprNoIn LE ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessEqNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExprNoIn GE ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterEqNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoIn '<' ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoIn '>' ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoIn LE ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessEqNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoIn GE ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterEqNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | RelationalExprNoIn INSTANCEOF ShiftExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new InstanceOfNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new InstanceOfNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 RelationalExprNoBF:
     ShiftExprNoBF
-  | RelationalExprNoBF '<' ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExprNoBF '>' ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExprNoBF LE ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessEqNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExprNoBF GE ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterEqNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoBF '<' ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoBF '>' ShiftExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoBF LE ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new LessEqNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoBF GE ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new GreaterEqNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | RelationalExprNoBF INSTANCEOF ShiftExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new InstanceOfNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | RelationalExprNoBF INTOKEN ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new InNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new InstanceOfNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | RelationalExprNoBF INTOKEN ShiftExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new InNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 EqualityExpr:
     RelationalExpr
-  | EqualityExpr EQEQ RelationalExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new EqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | EqualityExpr NE RelationalExpr      { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | EqualityExpr STREQ RelationalExpr   { $$ = createNodeFeatureInfo<ExpressionNode*>(new StrictEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | EqualityExpr STRNEQ RelationalExpr  { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotStrictEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | EqualityExpr EQEQ RelationalExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new EqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | EqualityExpr NE RelationalExpr      { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | EqualityExpr STREQ RelationalExpr   { $$ = createNodeFeatureInfo<ExpressionNode*>(new StrictEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | EqualityExpr STRNEQ RelationalExpr  { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotStrictEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 EqualityExprNoIn:
     RelationalExprNoIn
   | EqualityExprNoIn EQEQ RelationalExprNoIn
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new EqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new EqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | EqualityExprNoIn NE RelationalExprNoIn
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | EqualityExprNoIn STREQ RelationalExprNoIn
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new StrictEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new StrictEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | EqualityExprNoIn STRNEQ RelationalExprNoIn
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotStrictEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotStrictEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 EqualityExprNoBF:
     RelationalExprNoBF
   | EqualityExprNoBF EQEQ RelationalExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new EqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
-  | EqualityExprNoBF NE RelationalExpr  { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new EqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
+  | EqualityExprNoBF NE RelationalExpr  { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | EqualityExprNoBF STREQ RelationalExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new StrictEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new StrictEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
   | EqualityExprNoBF STRNEQ RelationalExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotStrictEqualNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new NotStrictEqualNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseANDExpr:
     EqualityExpr
-  | BitwiseANDExpr '&' EqualityExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitAndNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | BitwiseANDExpr '&' EqualityExpr     { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitAndNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseANDExprNoIn:
     EqualityExprNoIn
   | BitwiseANDExprNoIn '&' EqualityExprNoIn
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitAndNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitAndNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseANDExprNoBF:
     EqualityExprNoBF
-  | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitAndNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitAndNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseXORExpr:
     BitwiseANDExpr
-  | BitwiseXORExpr '^' BitwiseANDExpr   { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitXOrNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | BitwiseXORExpr '^' BitwiseANDExpr   { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitXOrNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseXORExprNoIn:
     BitwiseANDExprNoIn
   | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitXOrNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitXOrNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseXORExprNoBF:
     BitwiseANDExprNoBF
   | BitwiseXORExprNoBF '^' BitwiseANDExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitXOrNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitXOrNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseORExpr:
     BitwiseXORExpr
-  | BitwiseORExpr '|' BitwiseXORExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitOrNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+  | BitwiseORExpr '|' BitwiseXORExpr    { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitOrNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseORExprNoIn:
     BitwiseXORExprNoIn
   | BitwiseORExprNoIn '|' BitwiseXORExprNoIn
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitOrNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitOrNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 BitwiseORExprNoBF:
     BitwiseXORExprNoBF
   | BitwiseORExprNoBF '|' BitwiseXORExpr
-                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitOrNode($1.m_node, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitOrNode($1.m_node, $3.m_node, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo); }
 ;
 
 LogicalANDExpr:
index 57b10e90b00a3e455fb83911b8f0fac7ad7ca32f..dd06e1ddf09cdb7c35e51302c963b56a0819445a 100644 (file)
@@ -664,7 +664,7 @@ RegisterID* PreIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* ds
     if (RegisterID* local = generator.registerForLocal(m_ident)) {
         if (generator.isLocalConstant(m_ident)) {
             RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), 1.0);
-            return generator.emitAdd(r0.get(), local, r0.get());
+            return generator.emitBinaryOp(op_add, r0.get(), local, r0.get());
         }
         
         generator.emitPreInc(local);
@@ -692,7 +692,7 @@ RegisterID* PreDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* ds
     if (RegisterID* local = generator.registerForLocal(m_ident)) {
         if (generator.isLocalConstant(m_ident)) {
             RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), -1.0);
-            return generator.emitAdd(r0.get(), local, r0.get());
+            return generator.emitBinaryOp(op_add, r0.get(), local, r0.get());
         }
         
         generator.emitPreDec(local);
@@ -801,163 +801,20 @@ RegisterID* LogicalNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
     return generator.emitNot(generator.finalDestination(dst), src);
 }
 
-// ------------------------------ Multiplicative Nodes -----------------------------------
+// ------------------------------ Binary Operation Nodes -----------------------------------
 
-RegisterID* MultNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
-    RegisterID* src2 = generator.emitNode(m_term2.get());
-    return generator.emitMul(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* DivNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> dividend = generator.emitNode(m_term1.get());
-    RegisterID* divisor = generator.emitNode(m_term2.get());
-    return generator.emitDiv(generator.finalDestination(dst, dividend.get()), dividend.get(), divisor);
-}
-
-RegisterID* ModNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> dividend = generator.emitNode(m_term1.get());
-    RegisterID* divisor = generator.emitNode(m_term2.get());
-    return generator.emitMod(generator.finalDestination(dst, dividend.get()), dividend.get(), divisor);
-}
-
-// ------------------------------ Additive Nodes --------------------------------------
-
-RegisterID* AddNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2->isPure(generator));
     RegisterID* src2 = generator.emitNode(m_term2.get());
-    return generator.emitAdd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+    return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2);
 }
 
-RegisterID* SubNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2->isPure(generator));
     RegisterID* src2 = generator.emitNode(m_term2.get());
-    return generator.emitSub(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-// ------------------------------ Shift Nodes ------------------------------------
-
-RegisterID* LeftShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
-    RegisterID* shift = generator.emitNode(m_term2.get());
-    return generator.emitLeftShift(generator.finalDestination(dst, val.get()), val.get(), shift);
-}
-
-RegisterID* RightShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
-    RegisterID* shift = generator.emitNode(m_term2.get());
-    return generator.emitRightShift(generator.finalDestination(dst, val.get()), val.get(), shift);
-}
-
-RegisterID* UnsignedRightShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
-    RegisterID* shift = generator.emitNode(m_term2.get());
-    return generator.emitUnsignedRightShift(generator.finalDestination(dst, val.get()), val.get(), shift);
-}
-
-// ------------------------------ Relational Nodes -------------------------------
-
-RegisterID* LessNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitLess(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* GreaterNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitLess(generator.finalDestination(dst, src1.get()), src2, src1.get());
-}
-
-RegisterID* LessEqNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitLessEq(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* GreaterEqNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitLessEq(generator.finalDestination(dst, src1.get()), src2, src1.get());
-}
-
-RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> value = generator.emitNode(m_expr1.get());
-    RegisterID* base = generator.emitNode(m_expr2.get());
-    return generator.emitInstanceOf(generator.finalDestination(dst, value.get()), value.get(), base);
-}
-
-RegisterID* InNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> property = generator.emitNode(m_expr1.get());
-    RegisterID* base = generator.emitNode(m_expr2.get());
-    return generator.emitIn(generator.finalDestination(dst, property.get()), property.get(), base);
-}
-
-// ------------------------------ Equality Nodes ------------------------------------
-
-RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* NotEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitNotEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitStrictEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* NotStrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitNotStrictEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-// ------------------------------ Bit Operation Nodes ----------------------------------
-
-RegisterID* BitAndNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitBitAnd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* BitXOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitBitXOr(generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* BitOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
-    RegisterID* src2 = generator.emitNode(m_expr2.get());
-    return generator.emitBitOr(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+    return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get());
 }
 
 // ------------------------------ Binary Logical Nodes ----------------------------
@@ -1017,27 +874,27 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generat
 {
     switch (oper) {
         case OpMultEq:
-            return generator.emitMul(dst, src1, src2);
+            return generator.emitBinaryOp(op_mul, dst, src1, src2);
         case OpDivEq:
-            return generator.emitDiv(dst, src1, src2);
+            return generator.emitBinaryOp(op_div, dst, src1, src2);
         case OpPlusEq:
-            return generator.emitAdd(dst, src1, src2);
+            return generator.emitBinaryOp(op_add, dst, src1, src2);
         case OpMinusEq:
-            return generator.emitSub(dst, src1, src2);
+            return generator.emitBinaryOp(op_sub, dst, src1, src2);
         case OpLShift:
-            return generator.emitLeftShift(dst, src1, src2);
+            return generator.emitBinaryOp(op_lshift, dst, src1, src2);
         case OpRShift:
-            return generator.emitRightShift(dst, src1, src2);
+            return generator.emitBinaryOp(op_rshift, dst, src1, src2);
         case OpURShift:
-            return generator.emitUnsignedRightShift(dst, src1, src2);
+            return generator.emitBinaryOp(op_urshift, dst, src1, src2);
         case OpAndEq:
-            return generator.emitBitAnd(dst, src1, src2);
+            return generator.emitBinaryOp(op_bitand, dst, src1, src2);
         case OpXOrEq:
-            return generator.emitBitXOr(dst, src1, src2);
+            return generator.emitBinaryOp(op_bitxor, dst, src1, src2);
         case OpOrEq:
-            return generator.emitBitOr(dst, src1, src2);
+            return generator.emitBinaryOp(op_bitor, dst, src1, src2);
         case OpModEq:
-            return generator.emitMod(dst, src1, src2);
+            return generator.emitBinaryOp(op_mod, dst, src1, src2);
         default:
             ASSERT_NOT_REACHED();
     }
@@ -1572,14 +1429,14 @@ RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID
     // Setup jumps
     for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
         RegisterID* clauseVal = generator.emitNode(list->getClause()->expr());
-        generator.emitStrictEqual(clauseVal, clauseVal, switchExpression);
+        generator.emitBinaryOp(op_stricteq, clauseVal, clauseVal, switchExpression);
         labelVector.append(generator.newLabel());
         generator.emitJumpIfTrueMayCombine(clauseVal, labelVector[labelVector.size() - 1].get());
     }
 
     for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
         RegisterID* clauseVal = generator.emitNode(list->getClause()->expr());
-        generator.emitStrictEqual(clauseVal, clauseVal, switchExpression);
+        generator.emitBinaryOp(op_stricteq, clauseVal, clauseVal, switchExpression);
         labelVector.append(generator.newLabel());
         generator.emitJumpIfTrueMayCombine(clauseVal, labelVector[labelVector.size() - 1].get());
     }
index 9e08b3cce2f36186280579e3076c277e8838d521..c2046144689c3fc5e63067f5533f939f95a7c4df 100644 (file)
@@ -31,6 +31,7 @@
 #include "RegisterID.h"
 #include "SourceRange.h"
 #include "SymbolTable.h"
+#include "VM/Opcode.h"
 #include <wtf/UnusedParam.h>
 #include <wtf/ListRefPtr.h>
 #include <wtf/MathExtras.h>
@@ -1195,390 +1196,308 @@ namespace KJS {
         RefPtr<ExpressionNode> m_expr;
     };
 
-    class MultNode : public ExpressionNode {
+    class BinaryOpNode : public ExpressionNode {
     public:
-        MultNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
+        BinaryOpNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments)
+            : m_term1(term1)
+            , m_term2(term2)
+            , m_rightHasAssignments(rightHasAssignments)
+        {
+        }
+
+        BinaryOpNode(JSType type, ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments)
+            : ExpressionNode(type)
             , m_term1(term1)
             , m_term2(term2)
+            , m_rightHasAssignments(rightHasAssignments)
         {
         }
 
         virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
-        virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
-        virtual Precedence precedence() const { return PrecMultiplicitave; }
+        virtual OpcodeID opcode() const KJS_FAST_CALL = 0;
 
-    private:
+    protected:
         RefPtr<ExpressionNode> m_term1;
         RefPtr<ExpressionNode> m_term2;
+        bool m_rightHasAssignments;
     };
 
-    class DivNode : public ExpressionNode {
+    class ReverseBinaryOpNode : public ExpressionNode {
     public:
-        DivNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
+        ReverseBinaryOpNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments)
+            : m_term1(term1)
+            , m_term2(term2)
+            , m_rightHasAssignments(rightHasAssignments)
+        {
+        }
+
+        ReverseBinaryOpNode(JSType type, ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments)
+            : ExpressionNode(type)
             , m_term1(term1)
             , m_term2(term2)
+            , m_rightHasAssignments(rightHasAssignments)
         {
         }
 
         virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
-        virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
-        virtual Precedence precedence() const { return PrecMultiplicitave; }
+        virtual OpcodeID opcode() const KJS_FAST_CALL = 0;
 
-    private:
+    protected:
         RefPtr<ExpressionNode> m_term1;
         RefPtr<ExpressionNode> m_term2;
+        bool m_rightHasAssignments;
     };
 
-    class ModNode : public ExpressionNode {
+    class MultNode : public BinaryOpNode {
     public:
-        ModNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
-            , m_term1(term1)
-            , m_term2(term2)
+        MultNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_mul; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecMultiplicitave; }
+    };
 
-    private:
-        RefPtr<ExpressionNode> m_term1;
-        RefPtr<ExpressionNode> m_term2;
+    class DivNode : public BinaryOpNode {
+    public:
+        DivNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
+        {
+        }
+
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_div; }
+        virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+        virtual Precedence precedence() const { return PrecMultiplicitave; }
     };
 
-    class AddNode : public ExpressionNode {
+    class ModNode : public BinaryOpNode {
     public:
-        AddNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
-            : m_term1(term1)
-            , m_term2(term2)
-            , m_rightHasAssignments(rightHasAssignments)
+        ModNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_mod; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
-        virtual Precedence precedence() const { return PrecAdditive; }
+        virtual Precedence precedence() const { return PrecMultiplicitave; }
+    };
 
-    protected:
-        AddNode(ExpressionNode* term1, ExpressionNode* term2, JSType expectedReturn, bool rightHasAssignments) KJS_FAST_CALL
-            : ExpressionNode(expectedReturn)
-            , m_term1(term1)
-            , m_term2(term2)
-            , m_rightHasAssignments(rightHasAssignments)
+    class AddNode : public BinaryOpNode {
+    public:
+        AddNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(term1, term2, rightHasAssignments)
         {
         }
 
-        RefPtr<ExpressionNode> m_term1;
-        RefPtr<ExpressionNode> m_term2;
-        bool m_rightHasAssignments;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_add; }
+        virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+        virtual Precedence precedence() const { return PrecAdditive; }
     };
 
-    class SubNode : public ExpressionNode {
+    class SubNode : public BinaryOpNode {
     public:
         SubNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
-            , m_term1(term1)
-            , m_term2(term2)
-            , m_rightHasAssignments(rightHasAssignments)
+            : BinaryOpNode(term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_sub; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecAdditive; }
-
-    private:
-        RefPtr<ExpressionNode> m_term1;
-        RefPtr<ExpressionNode> m_term2;
-        bool m_rightHasAssignments;
     };
 
-    class LeftShiftNode : public ExpressionNode {
+    class LeftShiftNode : public BinaryOpNode {
     public:
-        LeftShiftNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
-            , m_term1(term1)
-            , m_term2(term2)
+        LeftShiftNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_lshift; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecShift; }
-
-    private:
-        RefPtr<ExpressionNode> m_term1;
-        RefPtr<ExpressionNode> m_term2;
     };
 
-    class RightShiftNode : public ExpressionNode {
+    class RightShiftNode : public BinaryOpNode {
     public:
-        RightShiftNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
-            , m_term1(term1)
-            , m_term2(term2)
+        RightShiftNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_rshift; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecShift; }
-
-    private:
-        RefPtr<ExpressionNode> m_term1;
-        RefPtr<ExpressionNode> m_term2;
     };
 
-    class UnsignedRightShiftNode : public ExpressionNode {
+    class UnsignedRightShiftNode : public BinaryOpNode {
     public:
-        UnsignedRightShiftNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
-            , m_term1(term1)
-            , m_term2(term2)
+        UnsignedRightShiftNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_urshift; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecShift; }
-
-    private:
-        RefPtr<ExpressionNode> m_term1;
-        RefPtr<ExpressionNode> m_term2;
     };
 
-    class LessNode : public ExpressionNode {
+    class LessNode : public BinaryOpNode {
     public:
-        LessNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(BooleanType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        LessNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_less; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecRelational; }
-
-    protected:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class GreaterNode : public ExpressionNode {
+    class GreaterNode : public ReverseBinaryOpNode {
     public:
-        GreaterNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : m_expr1(expr1)
-            , m_expr2(expr2)
+        GreaterNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : ReverseBinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_less; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecRelational; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class LessEqNode : public ExpressionNode {
+    class LessEqNode : public BinaryOpNode {
     public:
-        LessEqNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : m_expr1(expr1)
-            , m_expr2(expr2)
+        LessEqNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_lesseq; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecRelational; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class GreaterEqNode : public ExpressionNode {
+    class GreaterEqNode : public ReverseBinaryOpNode {
     public:
-        GreaterEqNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : m_expr1(expr1)
-            , m_expr2(expr2)
+        GreaterEqNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : ReverseBinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_lesseq; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecRelational; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class InstanceOfNode : public ExpressionNode {
+    class InstanceOfNode : public BinaryOpNode {
     public:
-        InstanceOfNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(BooleanType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        InstanceOfNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_instanceof; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecRelational; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class InNode : public ExpressionNode {
+    class InNode : public BinaryOpNode {
     public:
-        InNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : m_expr1(expr1)
-            , m_expr2(expr2)
+        InNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
-
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_in; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecRelational; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class EqualNode : public ExpressionNode {
+    class EqualNode : public BinaryOpNode {
     public:
-        EqualNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(BooleanType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        EqualNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_eq; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecEquality; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class NotEqualNode : public ExpressionNode {
+    class NotEqualNode : public BinaryOpNode {
     public:
-        NotEqualNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(BooleanType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        NotEqualNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_neq; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecEquality; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class StrictEqualNode : public ExpressionNode {
+    class StrictEqualNode : public BinaryOpNode {
     public:
-        StrictEqualNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(BooleanType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        StrictEqualNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_stricteq; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecEquality; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class NotStrictEqualNode : public ExpressionNode {
+    class NotStrictEqualNode : public BinaryOpNode {
     public:
-        NotStrictEqualNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(BooleanType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        NotStrictEqualNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(BooleanType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_nstricteq; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecEquality; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class BitAndNode : public ExpressionNode {
+    class BitAndNode : public BinaryOpNode {
     public:
-        BitAndNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        BitAndNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_bitand; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecBitwiseAnd; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class BitOrNode : public ExpressionNode {
+    class BitOrNode : public BinaryOpNode {
     public:
-        BitOrNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        BitOrNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_bitor; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecBitwiseOr; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
-    class BitXOrNode : public ExpressionNode {
+    class BitXOrNode : public BinaryOpNode {
     public:
-        BitXOrNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
-            : ExpressionNode(NumberType)
-            , m_expr1(expr1)
-            , m_expr2(expr2)
+        BitXOrNode(ExpressionNode* term1, ExpressionNode* term2, bool rightHasAssignments) KJS_FAST_CALL
+            : BinaryOpNode(NumberType, term1, term2, rightHasAssignments)
         {
         }
 
-        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+        virtual OpcodeID opcode() const KJS_FAST_CALL { return op_bitxor; }
         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
         virtual Precedence precedence() const { return PrecBitwiseXor; }
-
-    private:
-        RefPtr<ExpressionNode> m_expr1;
-        RefPtr<ExpressionNode> m_expr2;
     };
 
     /**
index 59b6dea031e6bb018c8df24df888f6430dbfb49e..7062c1a7c300579651896e9a95717dca86e32b3f 100644 (file)
@@ -629,67 +629,67 @@ void UnsignedRightShiftNode::streamTo(SourceStream& s) const
 
 void LessNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_term1, m_term2);
 }
 
 void GreaterNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_term1, m_term2);
 }
 
 void LessEqNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_term1, m_term2);
 }
 
 void GreaterEqNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_term1, m_term2);
 }
 
 void InstanceOfNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_term1, m_term2);
 }
 
 void InNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_term1, m_term2);
 }
 
 void EqualNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_term1, m_term2);
 }
 
 void NotEqualNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_term1, m_term2);
 }
 
 void StrictEqualNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_term1, m_term2);
 }
 
 void NotStrictEqualNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_term1, m_term2);
 }
 
 void BitAndNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_term1, m_term2);
 }
 
 void BitXOrNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_term1, m_term2);
 }
 
 void BitOrNode::streamTo(SourceStream& s) const
 {
-    streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_expr1, m_expr2);
+    streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_term1, m_term2);
 }
 
 void LogicalAndNode::streamTo(SourceStream& s) const
index c5a6c9a41b3521ee1711ad7e41b17d9925075fc4..0f5f192b630bc15de60d5140434237532cd8b138 100644 (file)
@@ -1,3 +1,15 @@
+2008-06-15  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
+
+        Reviewed by Maciej.
+
+        Tests for:
+
+        Bug 19484: More instructions needs to use temporary registers
+        <https://bugs.webkit.org/show_bug.cgi?id=19484>
+
+        * fast/js/codegen-temporaries-expected.txt:
+        * fast/js/resources/codegen-temporaries.js:
+
 2008-06-14  Darin Adler  <darin@apple.com>
 
         Reviewed by Maciej.
index 3cc82eba8a6c9feb5c0d5b15b9aaf83a34843d6c..16078bdd00d6b715ad5b0efb860533db2bcf554b 100644 (file)
@@ -42,12 +42,69 @@ PASS bracket_test3() is 0
 PASS bracket_test4() is 0
 PASS bracket_test5() is 1
 PASS bracket_test6() is 1
+PASS mult_test1() is 2
+PASS mult_test2() is 2
+PASS mult_test3() is 2
+PASS div_test1() is 0.5
+PASS div_test2() is 0.5
+PASS div_test3() is 0.5
+PASS mod_test1() is 1
+PASS mod_test2() is 1
+PASS mod_test3() is 1
 PASS add_test1() is 3
 PASS add_test2() is 3
 PASS add_test3() is 3
 PASS sub_test1() is -1
 PASS sub_test2() is -1
 PASS sub_test3() is -1
+PASS lshift_test1() is 4
+PASS lshift_test2() is 4
+PASS lshift_test3() is 4
+PASS rshift_test1() is 1
+PASS rshift_test2() is 1
+PASS rshift_test3() is 1
+PASS urshift_test1() is 1
+PASS urshift_test2() is 1
+PASS urshift_test3() is 1
+PASS less_test1() is true
+PASS less_test2() is true
+PASS less_test3() is true
+PASS greater_test1() is true
+PASS greater_test2() is true
+PASS greater_test3() is true
+PASS lesseq_test1() is true
+PASS lesseq_test2() is true
+PASS lesseq_test3() is true
+PASS greatereq_test1() is true
+PASS greatereq_test2() is true
+PASS greatereq_test3() is true
+PASS instanceof_test1() is true
+PASS instanceof_test2() is true
+PASS instanceof_test3() is true
+PASS in_test1() is true
+PASS in_test2() is true
+PASS in_test3() is true
+PASS eq_test1() is false
+PASS eq_test2() is false
+PASS eq_test3() is false
+PASS neq_test1() is true
+PASS neq_test2() is true
+PASS neq_test3() is true
+PASS stricteq_test1() is false
+PASS stricteq_test2() is false
+PASS stricteq_test3() is false
+PASS nstricteq_test1() is true
+PASS nstricteq_test2() is true
+PASS nstricteq_test3() is true
+PASS bitand_test1() is 0
+PASS bitand_test2() is 0
+PASS bitand_test3() is 0
+PASS bitor_test1() is 3
+PASS bitor_test2() is 3
+PASS bitor_test3() is 3
+PASS bitxor_test1() is 3
+PASS bitxor_test2() is 3
+PASS bitxor_test3() is 3
 PASS successfullyParsed is true
 
 TEST COMPLETE
index d92e265aa2833409ea6ce8c1d5839085a8b5839a..dc185a0959b03de6872fdc85d8077f5bcf5bd6a3 100644 (file)
@@ -350,6 +350,78 @@ function bracket_test6()
 
 shouldBe("bracket_test6()", "1");
 
+function mult_test1()
+{
+    var a = 1;
+    return a * (a = 2);
+}
+
+shouldBe("mult_test1()", "2");
+
+function mult_test2()
+{
+    var a = 1;
+    return a * ++a;
+}
+
+shouldBe("mult_test2()", "2");
+
+function mult_test3()
+{
+    var a = 1;
+    return a * (a += 1);
+}
+
+shouldBe("mult_test3()", "2");
+
+function div_test1()
+{
+    var a = 1;
+    return a / (a = 2);
+}
+
+shouldBe("div_test1()", "0.5");
+
+function div_test2()
+{
+    var a = 1;
+    return a / ++a;
+}
+
+shouldBe("div_test2()", "0.5");
+
+function div_test3()
+{
+    var a = 1;
+    return a / (a += 1);
+}
+
+shouldBe("div_test3()", "0.5");
+
+function mod_test1()
+{
+    var a = 1;
+    return a % (a = 2);
+}
+
+shouldBe("mod_test1()", "1");
+
+function mod_test2()
+{
+    var a = 1;
+    return a % ++a;
+}
+
+shouldBe("mod_test2()", "1");
+
+function mod_test3()
+{
+    var a = 1;
+    return a % (a += 1);
+}
+
+shouldBe("mod_test3()", "1");
+
 function add_test1()
 {
     var a = 1;
@@ -398,4 +470,388 @@ function sub_test3()
 
 shouldBe("sub_test3()", "-1");
 
-successfullyParsed = true;
+function lshift_test1()
+{
+    var a = 1;
+    return a << (a = 2);
+}
+
+shouldBe("lshift_test1()", "4");
+
+function lshift_test2()
+{
+    var a = 1;
+    return a << ++a;
+}
+
+shouldBe("lshift_test2()", "4");
+
+function lshift_test3()
+{
+    var a = 1;
+    return a << (a += 1);
+}
+
+shouldBe("lshift_test3()", "4");
+
+function rshift_test1()
+{
+    var a = 4;
+    return a >> (a = 2);
+}
+
+shouldBe("rshift_test1()", "1");
+
+function rshift_test2()
+{
+    var a = 2;
+    return a >> --a;
+}
+
+shouldBe("rshift_test2()", "1");
+
+function rshift_test3()
+{
+    var a = 2;
+    return a >> (a -= 1);
+}
+
+shouldBe("rshift_test3()", "1");
+
+function urshift_test1()
+{
+    var a = 4;
+    return a >>> (a = 2);
+}
+
+shouldBe("urshift_test1()", "1");
+
+function urshift_test2()
+{
+    var a = 2;
+    return a >>> --a;
+}
+
+shouldBe("urshift_test2()", "1");
+
+function urshift_test3()
+{
+    var a = 2;
+    return a >>> (a -= 1);
+}
+
+shouldBe("urshift_test3()", "1");
+
+function less_test1()
+{
+    var a = 1;
+    return a < (a = 2);
+}
+
+shouldBeTrue("less_test1()");
+
+function less_test2()
+{
+    var a = 1;
+    return a < ++a;
+}
+
+shouldBeTrue("less_test2()");
+
+function less_test3()
+{
+    var a = 1;
+    return a < (a += 1);
+}
+
+shouldBeTrue("less_test3()");
+
+function greater_test1()
+{
+    var a = 2;
+    return a > (a = 1);
+}
+
+shouldBeTrue("greater_test1()");
+
+function greater_test2()
+{
+    var a = 2;
+    return a > --a;
+}
+
+shouldBeTrue("greater_test2()");
+
+function greater_test3()
+{
+    var a = 2;
+    return a > (a -= 1);
+}
+
+shouldBeTrue("greater_test3()");
+
+function lesseq_test1()
+{
+    var a = 1;
+    return a <= (a = 3, 2);
+}
+
+shouldBeTrue("lesseq_test1()");
+
+function lesseq_test2()
+{
+    var a = 1;
+    return a <= (++a, 1);
+}
+
+shouldBeTrue("lesseq_test2()");
+
+function lesseq_test3()
+{
+    var a = 1;
+    return a <= (a += 1, 1);
+}
+
+shouldBeTrue("lesseq_test3()");
+
+function greatereq_test1()
+{
+    var a = 2;
+    return a >= (a = 1, 2);
+}
+
+shouldBeTrue("greatereq_test1()");
+
+function greatereq_test2()
+{
+    var a = 2;
+    return a >= (--a, 2);
+}
+
+shouldBeTrue("greatereq_test2()");
+
+function greatereq_test3()
+{
+    var a = 2;
+    return a >= (a -= 1, 2);
+}
+
+shouldBeTrue("greatereq_test3()");
+
+function instanceof_test1()
+{
+    var a = { };
+    return a instanceof (a = 1, Object);
+}
+
+shouldBeTrue("instanceof_test1()");
+
+function instanceof_test2()
+{
+    var a = { valueOf: function() { return 1; } };
+    return a instanceof (++a, Object);
+}
+
+shouldBeTrue("instanceof_test2()");
+
+function instanceof_test3()
+{
+    var a = { valueOf: function() { return 1; } };
+    return a instanceof (a += 1, Object);
+}
+
+shouldBeTrue("instanceof_test3()");
+
+function in_test1()
+{
+    var a = "a";
+    return a in (a = "b", { a: 1 });
+}
+
+shouldBeTrue("in_test1()");
+
+function in_test2()
+{
+    var a = { toString: function() { return "a"; }, valueOf: function() { return 1; } };
+    return a in (++a, { a: 1 });
+}
+
+shouldBeTrue("in_test2()");
+
+function in_test3()
+{
+    var a = { toString: function() { return "a"; }, valueOf: function() { return 1; } };
+    return a in (a += 1, { a: 1 });
+}
+
+shouldBeTrue("in_test3()");
+
+function eq_test1()
+{
+    var a = 1;
+    return a == (a = 2);
+}
+
+shouldBeFalse("eq_test1()");
+
+function eq_test2()
+{
+    var a = 1;
+    return a == ++a;
+}
+
+shouldBeFalse("eq_test2()");
+
+function eq_test3()
+{
+    var a = 1;
+    return a == (a += 1);
+}
+
+shouldBeFalse("eq_test3()");
+
+function neq_test1()
+{
+    var a = 1;
+    return a != (a = 2);
+}
+
+shouldBeTrue("neq_test1()");
+
+function neq_test2()
+{
+    var a = 1;
+    return a != ++a;
+}
+
+shouldBeTrue("neq_test2()");
+
+function neq_test3()
+{
+    var a = 1;
+    return a != (a += 1);
+}
+
+shouldBeTrue("neq_test3()");
+
+function stricteq_test1()
+{
+    var a = 1;
+    return a === (a = 2);
+}
+
+shouldBeFalse("stricteq_test1()");
+
+function stricteq_test2()
+{
+    var a = 1;
+    return a === ++a;
+}
+
+shouldBeFalse("stricteq_test2()");
+
+function stricteq_test3()
+{
+    var a = 1;
+    return a === (a += 1);
+}
+
+shouldBeFalse("stricteq_test3()");
+
+function nstricteq_test1()
+{
+    var a = 1;
+    return a !== (a = 2);
+}
+
+shouldBeTrue("nstricteq_test1()");
+
+function nstricteq_test2()
+{
+    var a = 1;
+    return a !== ++a;
+}
+
+shouldBeTrue("nstricteq_test2()");
+
+function nstricteq_test3()
+{
+    var a = 1;
+    return a !== (a += 1);
+}
+
+shouldBeTrue("nstricteq_test3()");
+
+function bitand_test1()
+{
+    var a = 1;
+    return a & (a = 2);
+}
+
+shouldBe("bitand_test1()", "0");
+
+function bitand_test2()
+{
+    var a = 1;
+    return a & ++a;
+}
+
+shouldBe("bitand_test2()", "0");
+
+function bitand_test3()
+{
+    var a = 1;
+    return a & (a += 1);
+}
+
+shouldBe("bitand_test3()", "0");
+
+function bitor_test1()
+{
+    var a = 1;
+    return a | (a = 2);
+}
+
+shouldBe("bitor_test1()", "3");
+
+function bitor_test2()
+{
+    var a = 1;
+    return a | ++a;
+}
+
+shouldBe("bitor_test2()", "3");
+
+function bitor_test3()
+{
+    var a = 1;
+    return a | (a += 1);
+}
+
+shouldBe("bitor_test3()", "3");
+
+function bitxor_test1()
+{
+    var a = 1;
+    return a ^ (a = 2);
+}
+
+shouldBe("bitxor_test1()", "3");
+
+function bitxor_test2()
+{
+    var a = 1;
+    return a ^ ++a;
+}
+
+shouldBe("bitxor_test2()", "3");
+
+function bitxor_test3()
+{
+    var a = 1;
+    return a ^ (a += 1);
+}
+
+shouldBe("bitxor_test3()", "3");
+
+var successfullyParsed = true;