Start using the overwrite mode from the full codegens to generate
authorkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 25 Aug 2010 11:10:05 +0000 (11:10 +0000)
committerkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 25 Aug 2010 11:10:05 +0000 (11:10 +0000)
slightly better code and allow passing arguments to binary op stubs
in registers on the platforms that support it.
Review URL: http://codereview.chromium.org/3203005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5339 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
src/arm/codegen-arm.cc
src/arm/full-codegen-arm.cc
src/ast.cc
src/ast.h
src/full-codegen.cc
src/full-codegen.h
src/ia32/code-stubs-ia32.h
src/ia32/codegen-ia32.cc
src/ia32/full-codegen-ia32.cc
src/x64/code-stubs-x64.h
src/x64/codegen-x64.cc
src/x64/full-codegen-x64.cc

index 89c51a2..5b7b0d5 100644 (file)
@@ -3550,9 +3550,7 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) {
 
     // Perform the binary operation.
     Literal* literal = node->value()->AsLiteral();
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     if (literal != NULL && literal->handle()->IsSmi()) {
       SmiOperation(node->binary_op(),
                    literal->handle(),
@@ -3650,9 +3648,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
 
     // Perform the binary operation.
     Literal* literal = node->value()->AsLiteral();
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     if (literal != NULL && literal->handle()->IsSmi()) {
       SmiOperation(node->binary_op(),
                    literal->handle(),
@@ -3766,9 +3762,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
 
     // Perform the binary operation.
     Literal* literal = node->value()->AsLiteral();
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     if (literal != NULL && literal->handle()->IsSmi()) {
       SmiOperation(node->binary_op(),
                    literal->handle(),
@@ -5755,9 +5749,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
     frame_->EmitPush(r0);  // r0 has result
 
   } else {
-    bool can_overwrite =
-        (node->expression()->AsBinaryOperation() != NULL &&
-         node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool can_overwrite = node->expression()->ResultOverwriteAllowed();
     UnaryOverwriteMode overwrite =
         can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
 
@@ -6081,12 +6073,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
     Literal* rliteral = node->right()->AsLiteral();
     // NOTE: The code below assumes that the slow cases (calls to runtime)
     // never return a constant/immutable object.
-    bool overwrite_left =
-        (node->left()->AsBinaryOperation() != NULL &&
-         node->left()->AsBinaryOperation()->ResultOverwriteAllowed());
-    bool overwrite_right =
-        (node->right()->AsBinaryOperation() != NULL &&
-         node->right()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_left = node->left()->ResultOverwriteAllowed();
+    bool overwrite_right = node->right()->ResultOverwriteAllowed();
 
     if (rliteral != NULL && rliteral->handle()->IsSmi()) {
       VirtualFrame::RegisterAllocationScope scope(this);
index 3c48dbd..a0505a7 100644 (file)
@@ -1207,7 +1207,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
   if (expr->is_compound()) {
     Location saved_location = location_;
     location_ = kAccumulator;
-    EmitBinaryOp(expr->binary_op(), Expression::kValue);
+    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
+        ? OVERWRITE_RIGHT
+        : NO_OVERWRITE;
+    EmitBinaryOp(expr->binary_op(), Expression::kValue, mode);
     location_ = saved_location;
   }
 
@@ -1250,9 +1253,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 
 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
-                                     Expression::Context context) {
+                                     Expression::Context context,
+                                     OverwriteMode mode) {
   __ pop(r1);
-  GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0);
+  GenericBinaryOpStub stub(op, mode, r1, r0);
   __ CallStub(&stub);
   Apply(context, r0);
 }
@@ -2654,9 +2658,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
 
     case Token::SUB: {
       Comment cmt(masm_, "[ UnaryOperation (SUB)");
-      bool can_overwrite =
-          (expr->expression()->AsBinaryOperation() != NULL &&
-           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
       UnaryOverwriteMode overwrite =
           can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
       GenericUnaryOpStub stub(Token::SUB, overwrite);
@@ -2670,9 +2672,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
 
     case Token::BIT_NOT: {
       Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
-      bool can_overwrite =
-          (expr->expression()->AsBinaryOperation() != NULL &&
-           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
       UnaryOverwriteMode overwrite =
           can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
       GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
@@ -2791,7 +2791,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
   // Inline smi case if we are in a loop.
   Label stub_call, done;
   int count_value = expr->op() == Token::INC ? 1 : -1;
-  if (loop_depth() > 0) {
+  if (ShouldInlineSmiCase(expr->op())) {
     __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
     __ b(vs, &stub_call);
     // We could eliminate this smi check if we split the code at
@@ -2998,7 +2998,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   }
 
   VisitForValue(expr->left(), kStack);
-  switch (expr->op()) {
+  switch (op) {
     case Token::IN:
       VisitForValue(expr->right(), kStack);
       __ InvokeBuiltin(Builtins::IN, CALL_JS);
@@ -3021,7 +3021,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
       VisitForValue(expr->right(), kAccumulator);
       Condition cc = eq;
       bool strict = false;
-      switch (expr->op()) {
+      switch (op) {
         case Token::EQ_STRICT:
           strict = true;
           // Fall through
index 97f9245..0d07a58 100644 (file)
@@ -239,6 +239,42 @@ void Expression::CopyAnalysisResultsFrom(Expression* other) {
 }
 
 
+bool UnaryOperation::ResultOverwriteAllowed() {
+  switch (op_) {
+    case Token::BIT_NOT:
+    case Token::SUB:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+bool BinaryOperation::ResultOverwriteAllowed() {
+  switch (op_) {
+    case Token::COMMA:
+    case Token::OR:
+    case Token::AND:
+      return false;
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND:
+    case Token::SHL:
+    case Token::SAR:
+    case Token::SHR:
+    case Token::ADD:
+    case Token::SUB:
+    case Token::MUL:
+    case Token::DIV:
+    case Token::MOD:
+      return true;
+    default:
+      UNREACHABLE();
+  }
+  return false;
+}
+
+
 BinaryOperation::BinaryOperation(Assignment* assignment) {
   ASSERT(assignment->is_compound());
   op_ = assignment->binary_op();
index 3bc9b17..d1a740c 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -201,6 +201,10 @@ class Expression: public AstNode {
   // (faster) prefix increments.
   virtual void MarkAsStatement() { /* do nothing */ }
 
+  // True iff the result can be safely overwritten (to avoid allocation).
+  // False for operations that can return one of their operands.
+  virtual bool ResultOverwriteAllowed() { return false; }
+
   // Static type information for this expression.
   StaticType* type() { return &type_; }
 
@@ -1187,6 +1191,7 @@ class UnaryOperation: public Expression {
   }
 
   virtual void Accept(AstVisitor* v);
+  virtual bool ResultOverwriteAllowed();
 
   // Type testing & conversion
   virtual UnaryOperation* AsUnaryOperation() { return this; }
@@ -1214,36 +1219,11 @@ class BinaryOperation: public Expression {
   explicit BinaryOperation(Assignment* assignment);
 
   virtual void Accept(AstVisitor* v);
+  virtual bool ResultOverwriteAllowed();
 
   // Type testing & conversion
   virtual BinaryOperation* AsBinaryOperation() { return this; }
 
-  // True iff the result can be safely overwritten (to avoid allocation).
-  // False for operations that can return one of their operands.
-  bool ResultOverwriteAllowed() {
-    switch (op_) {
-      case Token::COMMA:
-      case Token::OR:
-      case Token::AND:
-        return false;
-      case Token::BIT_OR:
-      case Token::BIT_XOR:
-      case Token::BIT_AND:
-      case Token::SHL:
-      case Token::SAR:
-      case Token::SHR:
-      case Token::ADD:
-      case Token::SUB:
-      case Token::MUL:
-      case Token::DIV:
-      case Token::MOD:
-        return true;
-      default:
-        UNREACHABLE();
-    }
-    return false;
-  }
-
   Token::Value op() const { return op_; }
   Expression* left() const { return left_; }
   Expression* right() const { return right_; }
index 2402fda..c33f1f9 100644 (file)
@@ -317,6 +317,13 @@ int FullCodeGenerator::SlotOffset(Slot* slot) {
 }
 
 
+bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
+  if (Debugger::IsDebuggerActive()) return false;
+  if (op == Token::DIV ||op == Token::MOD) return false;
+  return loop_depth_ > 0;
+}
+
+
 void FullCodeGenerator::PrepareTest(Label* materialize_true,
                                     Label* materialize_false,
                                     Label** if_true,
@@ -503,6 +510,14 @@ void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
 
 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
   Comment cmnt(masm_, "[ BinaryOperation");
+
+  OverwriteMode overwrite_mode = NO_OVERWRITE;
+  if (expr->left()->ResultOverwriteAllowed()) {
+    overwrite_mode = OVERWRITE_LEFT;
+  } else if (expr->right()->ResultOverwriteAllowed()) {
+    overwrite_mode = OVERWRITE_RIGHT;
+  }
+
   switch (expr->op()) {
     case Token::COMMA:
       VisitForEffect(expr->left());
@@ -528,7 +543,7 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
       VisitForValue(expr->left(), kStack);
       VisitForValue(expr->right(), kAccumulator);
       SetSourcePosition(expr->position());
-      EmitBinaryOp(expr->op(), context_);
+      EmitBinaryOp(expr->op(), context_, overwrite_mode);
       break;
 
     default:
index 8f5f07f..1f75279 100644 (file)
@@ -237,8 +237,14 @@ class FullCodeGenerator: public AstVisitor {
     kStack
   };
 
+  // Compute the frame pointer relative offset for a given local or
+  // parameter slot.
   int SlotOffset(Slot* slot);
 
+  // Determine whether or not to inline the smi case for the given
+  // operation.
+  bool ShouldInlineSmiCase(Token::Value op);
+
   // Emit code to convert a pure value (in a register, slot, as a literal,
   // or on top of the stack) into the result expected according to an
   // expression context.
@@ -383,7 +389,9 @@ class FullCodeGenerator: public AstVisitor {
 
   // Apply the compound assignment operator. Expects the left operand on top
   // of the stack and the right one in the accumulator.
-  void EmitBinaryOp(Token::Value op, Expression::Context context);
+  void EmitBinaryOp(Token::Value op,
+                    Expression::Context context,
+                    OverwriteMode mode);
 
   // Assign to the given expression as if via '='. The right-hand-side value
   // is expected in the accumulator.
index c258302..abd41e3 100644 (file)
@@ -117,6 +117,11 @@ class GenericBinaryOpStub: public CodeStub {
                       Result* left,
                       Result* right);
 
+  bool ArgsInRegistersSupported() {
+    return op_ == Token::ADD || op_ == Token::SUB
+        || op_ == Token::MUL || op_ == Token::DIV;
+  }
+
  private:
   Token::Value op_;
   OverwriteMode mode_;
@@ -181,10 +186,6 @@ class GenericBinaryOpStub: public CodeStub {
   void GenerateRegisterArgsPush(MacroAssembler* masm);
   void GenerateTypeTransition(MacroAssembler* masm);
 
-  bool ArgsInRegistersSupported() {
-    return op_ == Token::ADD || op_ == Token::SUB
-        || op_ == Token::MUL || op_ == Token::DIV;
-  }
   bool IsOperationCommutative() {
     return (op_ == Token::ADD) || (op_ == Token::MUL);
   }
index 39208b8..c431999 100644 (file)
@@ -5692,9 +5692,7 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) {
     Load(node->value());
 
     // Perform the binary operation.
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     // Construct the implicit binary operation.
     BinaryOperation expr(node);
     GenericBinaryOperation(&expr,
@@ -5783,9 +5781,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
     frame()->Push(&value);
     Load(node->value());
 
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     // Construct the implicit binary operation.
     BinaryOperation expr(node);
     GenericBinaryOperation(&expr,
@@ -5885,9 +5881,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
     Load(node->value());
 
     // Perform the binary operation.
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     BinaryOperation expr(node);
     GenericBinaryOperation(&expr,
                            overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
@@ -8087,9 +8081,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
       frame_->Push(&value);
     } else {
       Load(node->expression());
-      bool can_overwrite =
-          (node->expression()->AsBinaryOperation() != NULL &&
-           node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      bool can_overwrite = node->expression()->ResultOverwriteAllowed();
       UnaryOverwriteMode overwrite =
           can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
       bool no_negative_zero = node->expression()->no_negative_zero();
@@ -8794,11 +8786,9 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
     // NOTE: The code below assumes that the slow cases (calls to runtime)
     // never return a constant/immutable object.
     OverwriteMode overwrite_mode = NO_OVERWRITE;
-    if (node->left()->AsBinaryOperation() != NULL &&
-        node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
+    if (node->left()->ResultOverwriteAllowed()) {
       overwrite_mode = OVERWRITE_LEFT;
-    } else if (node->right()->AsBinaryOperation() != NULL &&
-               node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
+    } else if (node->right()->ResultOverwriteAllowed()) {
       overwrite_mode = OVERWRITE_RIGHT;
     }
 
index 707c07e..d804ce9 100644 (file)
@@ -1214,7 +1214,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
   if (expr->is_compound()) {
     Location saved_location = location_;
     location_ = kAccumulator;
-    EmitBinaryOp(expr->binary_op(), Expression::kValue);
+    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
+        ? OVERWRITE_RIGHT
+        : NO_OVERWRITE;
+    EmitBinaryOp(expr->binary_op(), Expression::kValue, mode);
     location_ = saved_location;
   }
 
@@ -1257,13 +1260,17 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 
 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
-                                     Expression::Context context) {
-  __ push(result_register());
-  GenericBinaryOpStub stub(op,
-                           NO_OVERWRITE,
-                           NO_GENERIC_BINARY_FLAGS,
-                           TypeInfo::Unknown());
-  __ CallStub(&stub);
+                                     Expression::Context context,
+                                     OverwriteMode mode) {
+  TypeInfo type = TypeInfo::Unknown();
+  GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS, type);
+  if (stub.ArgsInRegistersSupported()) {
+    __ pop(edx);
+    stub.GenerateCall(masm_, edx, eax);
+  } else {
+    __ push(result_register());
+    __ CallStub(&stub);
+  }
   Apply(context, eax);
 }
 
@@ -2651,9 +2658,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
 
     case Token::SUB: {
       Comment cmt(masm_, "[ UnaryOperation (SUB)");
-      bool can_overwrite =
-          (expr->expression()->AsBinaryOperation() != NULL &&
-           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
       UnaryOverwriteMode overwrite =
           can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
       GenericUnaryOpStub stub(Token::SUB, overwrite);
@@ -2667,9 +2672,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
 
     case Token::BIT_NOT: {
       Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
-      bool can_overwrite =
-          (expr->expression()->AsBinaryOperation() != NULL &&
-           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
       UnaryOverwriteMode overwrite =
           can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
       GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
@@ -2750,8 +2753,10 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
   // Call ToNumber only if operand is not a smi.
   Label no_conversion;
-  __ test(eax, Immediate(kSmiTagMask));
-  __ j(zero, &no_conversion);
+  if (ShouldInlineSmiCase(expr->op())) {
+    __ test(eax, Immediate(kSmiTagMask));
+    __ j(zero, &no_conversion);
+  }
   __ push(eax);
   __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
   __ bind(&no_conversion);
@@ -2786,7 +2791,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
   // Inline smi case if we are in a loop.
   Label stub_call, done;
-  if (loop_depth() > 0) {
+  if (ShouldInlineSmiCase(expr->op())) {
     if (expr->op() == Token::INC) {
       __ add(Operand(eax), Immediate(Smi::FromInt(1)));
     } else {
@@ -3027,7 +3032,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
       VisitForValue(expr->right(), kAccumulator);
       Condition cc = no_condition;
       bool strict = false;
-      switch (expr->op()) {
+      switch (op) {
         case Token::EQ_STRICT:
           strict = true;
           // Fall through
@@ -3061,8 +3066,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
           UNREACHABLE();
       }
 
-      // The comparison stub expects the smi vs. smi case to be handled
-      // before it is called.
+      // The comparison stub expects the smi vs. smi case to be
+      // handled before it is called.
       Label slow_case;
       __ mov(ecx, Operand(edx));
       __ or_(ecx, Operand(eax));
index a83643b..149b6de 100644 (file)
@@ -112,6 +112,11 @@ class GenericBinaryOpStub: public CodeStub {
                       Result* left,
                       Result* right);
 
+  bool ArgsInRegistersSupported() {
+    return (op_ == Token::ADD) || (op_ == Token::SUB)
+        || (op_ == Token::MUL) || (op_ == Token::DIV);
+  }
+
  private:
   Token::Value op_;
   OverwriteMode mode_;
@@ -172,10 +177,6 @@ class GenericBinaryOpStub: public CodeStub {
   void GenerateRegisterArgsPush(MacroAssembler* masm);
   void GenerateTypeTransition(MacroAssembler* masm);
 
-  bool ArgsInRegistersSupported() {
-    return (op_ == Token::ADD) || (op_ == Token::SUB)
-        || (op_ == Token::MUL) || (op_ == Token::DIV);
-  }
   bool IsOperationCommutative() {
     return (op_ == Token::ADD) || (op_ == Token::MUL);
   }
index 5cb5b10..e003520 100644 (file)
@@ -5009,9 +5009,7 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) {
     Load(node->value());
 
     // Perform the binary operation.
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     // Construct the implicit binary operation.
     BinaryOperation expr(node);
     GenericBinaryOperation(&expr,
@@ -5100,9 +5098,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
     frame()->Push(&value);
     Load(node->value());
 
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     // Construct the implicit binary operation.
     BinaryOperation expr(node);
     GenericBinaryOperation(&expr,
@@ -5202,9 +5198,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
     Load(node->value());
 
     // Perform the binary operation.
-    bool overwrite_value =
-        (node->value()->AsBinaryOperation() != NULL &&
-         node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool overwrite_value = node->value()->ResultOverwriteAllowed();
     BinaryOperation expr(node);
     GenericBinaryOperation(&expr,
                            overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
@@ -7357,9 +7351,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
     }
 
   } else {
-    bool can_overwrite =
-      (node->expression()->AsBinaryOperation() != NULL &&
-       node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+    bool can_overwrite = node->expression()->ResultOverwriteAllowed();
     UnaryOverwriteMode overwrite =
         can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
     bool no_negative_zero = node->expression()->no_negative_zero();
@@ -7777,11 +7769,9 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
     // NOTE: The code below assumes that the slow cases (calls to runtime)
     // never return a constant/immutable object.
     OverwriteMode overwrite_mode = NO_OVERWRITE;
-    if (node->left()->AsBinaryOperation() != NULL &&
-        node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
+    if (node->left()->ResultOverwriteAllowed()) {
       overwrite_mode = OVERWRITE_LEFT;
-    } else if (node->right()->AsBinaryOperation() != NULL &&
-               node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
+    } else if (node->right()->ResultOverwriteAllowed()) {
       overwrite_mode = OVERWRITE_RIGHT;
     }
 
index 94fd19d..45e721a 100644 (file)
@@ -1218,7 +1218,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
   if (expr->is_compound()) {
     Location saved_location = location_;
     location_ = kAccumulator;
-    EmitBinaryOp(expr->binary_op(), Expression::kValue);
+    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
+        ? OVERWRITE_RIGHT
+        : NO_OVERWRITE;
+    EmitBinaryOp(expr->binary_op(), Expression::kValue, mode);
     location_ = saved_location;
   }
 
@@ -1261,12 +1264,16 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
 
 
 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
-                                     Expression::Context context) {
-  __ push(result_register());
-  GenericBinaryOpStub stub(op,
-                           NO_OVERWRITE,
-                           NO_GENERIC_BINARY_FLAGS);
-  __ CallStub(&stub);
+                                     Expression::Context context,
+                                     OverwriteMode mode) {
+  GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS);
+  if (stub.ArgsInRegistersSupported()) {
+    __ pop(rdx);
+    stub.GenerateCall(masm_, rdx, rax);
+  } else {
+    __ push(result_register());
+    __ CallStub(&stub);
+  }
   Apply(context, rax);
 }
 
@@ -2646,9 +2653,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
 
     case Token::SUB: {
       Comment cmt(masm_, "[ UnaryOperation (SUB)");
-      bool can_overwrite =
-          (expr->expression()->AsBinaryOperation() != NULL &&
-           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
       UnaryOverwriteMode overwrite =
           can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
       GenericUnaryOpStub stub(Token::SUB, overwrite);
@@ -2662,9 +2667,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
 
     case Token::BIT_NOT: {
       Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
-      bool can_overwrite =
-          (expr->expression()->AsBinaryOperation() != NULL &&
-           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
       UnaryOverwriteMode overwrite =
           can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
       GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
@@ -2780,7 +2783,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
   // Inline smi case if we are in a loop.
   Label stub_call, done;
-  if (loop_depth() > 0) {
+  if (ShouldInlineSmiCase(expr->op())) {
     if (expr->op() == Token::INC) {
       __ SmiAddConstant(rax, rax, Smi::FromInt(1));
     } else {
@@ -2995,7 +2998,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   }
 
   VisitForValue(expr->left(), kStack);
-  switch (expr->op()) {
+  switch (op) {
     case Token::IN:
       VisitForValue(expr->right(), kStack);
       __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
@@ -3017,7 +3020,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
       VisitForValue(expr->right(), kAccumulator);
       Condition cc = no_condition;
       bool strict = false;
-      switch (expr->op()) {
+      switch (op) {
         case Token::EQ_STRICT:
           strict = true;
           // Fall through.