| Index: src/ia32/codegen-ia32.cc
 | 
| ===================================================================
 | 
| --- src/ia32/codegen-ia32.cc	(revision 4088)
 | 
| +++ src/ia32/codegen-ia32.cc	(working copy)
 | 
| @@ -2286,69 +2286,61 @@
 | 
|        // a jump target and branching to duplicate the virtual frame at
 | 
|        // the first split.  We manually handle the off-frame references
 | 
|        // by reconstituting them on the non-fall-through path.
 | 
| +      JumpTarget is_smi;
 | 
| +      __ test(left_side.reg(), Immediate(kSmiTagMask));
 | 
| +      is_smi.Branch(zero, taken);
 | 
|  
 | 
| -      if (left_side.is_smi()) {
 | 
| -        if (FLAG_debug_code) {
 | 
| -          __ AbortIfNotSmi(left_side.reg(), "Argument not a smi");
 | 
| +      bool is_for_loop_compare = (node->AsCompareOperation() != NULL)
 | 
| +          && node->AsCompareOperation()->is_for_loop_condition();
 | 
| +      if (!is_for_loop_compare
 | 
| +          && CpuFeatures::IsSupported(SSE2)
 | 
| +          && right_val->IsSmi()) {
 | 
| +        // Right side is a constant smi and left side has been checked
 | 
| +        // not to be a smi.
 | 
| +        CpuFeatures::Scope use_sse2(SSE2);
 | 
| +        JumpTarget not_number;
 | 
| +        __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
 | 
| +               Immediate(Factory::heap_number_map()));
 | 
| +        not_number.Branch(not_equal, &left_side);
 | 
| +        __ movdbl(xmm1,
 | 
| +                  FieldOperand(left_reg, HeapNumber::kValueOffset));
 | 
| +        int value = Smi::cast(*right_val)->value();
 | 
| +        if (value == 0) {
 | 
| +          __ xorpd(xmm0, xmm0);
 | 
| +        } else {
 | 
| +          Result temp = allocator()->Allocate();
 | 
| +          __ mov(temp.reg(), Immediate(value));
 | 
| +          __ cvtsi2sd(xmm0, Operand(temp.reg()));
 | 
| +          temp.Unuse();
 | 
|          }
 | 
| -      } else {
 | 
| -        JumpTarget is_smi;
 | 
| -        __ test(left_side.reg(), Immediate(kSmiTagMask));
 | 
| -        is_smi.Branch(zero, taken);
 | 
| -
 | 
| -        bool is_for_loop_compare = (node->AsCompareOperation() != NULL)
 | 
| -            && node->AsCompareOperation()->is_for_loop_condition();
 | 
| -        if (!is_for_loop_compare
 | 
| -            && CpuFeatures::IsSupported(SSE2)
 | 
| -            && right_val->IsSmi()) {
 | 
| -          // Right side is a constant smi and left side has been checked
 | 
| -          // not to be a smi.
 | 
| -          CpuFeatures::Scope use_sse2(SSE2);
 | 
| -          JumpTarget not_number;
 | 
| -          __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
 | 
| -                 Immediate(Factory::heap_number_map()));
 | 
| -          not_number.Branch(not_equal, &left_side);
 | 
| -          __ movdbl(xmm1,
 | 
| -                    FieldOperand(left_reg, HeapNumber::kValueOffset));
 | 
| -          int value = Smi::cast(*right_val)->value();
 | 
| -          if (value == 0) {
 | 
| -            __ xorpd(xmm0, xmm0);
 | 
| -          } else {
 | 
| -            Result temp = allocator()->Allocate();
 | 
| -            __ mov(temp.reg(), Immediate(value));
 | 
| -            __ cvtsi2sd(xmm0, Operand(temp.reg()));
 | 
| -            temp.Unuse();
 | 
| -          }
 | 
| -          __ comisd(xmm1, xmm0);
 | 
| -          // Jump to builtin for NaN.
 | 
| -          not_number.Branch(parity_even, &left_side);
 | 
| -          left_side.Unuse();
 | 
| -          Condition double_cc = cc;
 | 
| -          switch (cc) {
 | 
| -            case less:          double_cc = below;       break;
 | 
| -            case equal:         double_cc = equal;       break;
 | 
| -            case less_equal:    double_cc = below_equal; break;
 | 
| -            case greater:       double_cc = above;       break;
 | 
| -            case greater_equal: double_cc = above_equal; break;
 | 
| -            default: UNREACHABLE();
 | 
| -          }
 | 
| -          dest->true_target()->Branch(double_cc);
 | 
| -          dest->false_target()->Jump();
 | 
| -          not_number.Bind(&left_side);
 | 
| +        __ comisd(xmm1, xmm0);
 | 
| +        // Jump to builtin for NaN.
 | 
| +        not_number.Branch(parity_even, &left_side);
 | 
| +        left_side.Unuse();
 | 
| +        Condition double_cc = cc;
 | 
| +        switch (cc) {
 | 
| +          case less:          double_cc = below;       break;
 | 
| +          case equal:         double_cc = equal;       break;
 | 
| +          case less_equal:    double_cc = below_equal; break;
 | 
| +          case greater:       double_cc = above;       break;
 | 
| +          case greater_equal: double_cc = above_equal; break;
 | 
| +          default: UNREACHABLE();
 | 
|          }
 | 
| -
 | 
| -        // Setup and call the compare stub.
 | 
| -        CompareStub stub(cc, strict, kCantBothBeNaN);
 | 
| -        Result result = frame_->CallStub(&stub, &left_side, &right_side);
 | 
| -        result.ToRegister();
 | 
| -        __ cmp(result.reg(), 0);
 | 
| -        result.Unuse();
 | 
| -        dest->true_target()->Branch(cc);
 | 
| +        dest->true_target()->Branch(double_cc);
 | 
|          dest->false_target()->Jump();
 | 
| -
 | 
| -        is_smi.Bind();
 | 
| +        not_number.Bind(&left_side);
 | 
|        }
 | 
|  
 | 
| +      // Setup and call the compare stub.
 | 
| +      CompareStub stub(cc, strict, kCantBothBeNaN);
 | 
| +      Result result = frame_->CallStub(&stub, &left_side, &right_side);
 | 
| +      result.ToRegister();
 | 
| +      __ cmp(result.reg(), 0);
 | 
| +      result.Unuse();
 | 
| +      dest->true_target()->Branch(cc);
 | 
| +      dest->false_target()->Jump();
 | 
| +
 | 
| +      is_smi.Bind();
 | 
|        left_side = Result(left_reg);
 | 
|        right_side = Result(right_val);
 | 
|        // Test smi equality and comparison by signed int comparison.
 | 
| @@ -3587,24 +3579,6 @@
 | 
|    }
 | 
|  
 | 
|    CheckStack();  // TODO(1222600): ignore if body contains calls.
 | 
| -
 | 
| -  // If we have (a) a loop with a compile-time constant trip count
 | 
| -  // and (b) the loop induction variable is not assignend inside the
 | 
| -  // loop we update the number type of the induction variable to be smi.
 | 
| -
 | 
| -  if (node->is_fast_smi_loop()) {
 | 
| -    // Set number type of the loop variable to smi.
 | 
| -    Slot* slot = node->loop_variable()->slot();
 | 
| -    ASSERT(slot->type() == Slot::LOCAL);
 | 
| -    frame_->SetTypeForLocalAt(slot->index(), NumberInfo::Smi());
 | 
| -    if (FLAG_debug_code) {
 | 
| -      frame_->PushLocalAt(slot->index());
 | 
| -      Result var = frame_->Pop();
 | 
| -      var.ToRegister();
 | 
| -      __ AbortIfNotSmi(var.reg(), "Loop variable not a smi.");
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
|    Visit(node->body());
 | 
|  
 | 
|    // If there is an update expression, compile it if necessary.
 | 
| @@ -6650,6 +6624,15 @@
 | 
|        __ Set(tmp.reg(), Immediate(0));
 | 
|      }
 | 
|  
 | 
| +    DeferredCode* deferred = NULL;
 | 
| +    if (is_postfix) {
 | 
| +      deferred = new DeferredPostfixCountOperation(new_value.reg(),
 | 
| +                                                   old_value.reg(),
 | 
| +                                                   is_increment);
 | 
| +    } else {
 | 
| +      deferred = new DeferredPrefixCountOperation(new_value.reg(),
 | 
| +                                                  is_increment);
 | 
| +    }
 | 
|  
 | 
|      if (is_increment) {
 | 
|        __ add(Operand(new_value.reg()), Immediate(Smi::FromInt(1)));
 | 
| @@ -6657,41 +6640,24 @@
 | 
|        __ sub(Operand(new_value.reg()), Immediate(Smi::FromInt(1)));
 | 
|      }
 | 
|  
 | 
| -    if (new_value.is_smi()) {
 | 
| -      if (FLAG_debug_code) {
 | 
| -        __ AbortIfNotSmi(new_value.reg(), "Argument not a smi");
 | 
| -      }
 | 
| -      if (tmp.is_valid()) tmp.Unuse();
 | 
| +    // If the count operation didn't overflow and the result is a valid
 | 
| +    // smi, we're done. Otherwise, we jump to the deferred slow-case
 | 
| +    // code.
 | 
| +    if (tmp.is_valid()) {
 | 
| +      // We combine the overflow and the smi tag check if we could
 | 
| +      // successfully allocate a temporary byte register.
 | 
| +      __ setcc(overflow, tmp.reg());
 | 
| +      __ or_(Operand(tmp.reg()), new_value.reg());
 | 
| +      __ test(tmp.reg(), Immediate(kSmiTagMask));
 | 
| +      tmp.Unuse();
 | 
| +      deferred->Branch(not_zero);
 | 
|      } else {
 | 
| -      DeferredCode* deferred = NULL;
 | 
| -      if (is_postfix) {
 | 
| -        deferred = new DeferredPostfixCountOperation(new_value.reg(),
 | 
| -                                                     old_value.reg(),
 | 
| -                                                     is_increment);
 | 
| -      } else {
 | 
| -        deferred = new DeferredPrefixCountOperation(new_value.reg(),
 | 
| -                                                    is_increment);
 | 
| -      }
 | 
| -
 | 
| -      // If the count operation didn't overflow and the result is a valid
 | 
| -      // smi, we're done. Otherwise, we jump to the deferred slow-case
 | 
| -      // code.
 | 
| -      if (tmp.is_valid()) {
 | 
| -        // We combine the overflow and the smi tag check if we could
 | 
| -        // successfully allocate a temporary byte register.
 | 
| -        __ setcc(overflow, tmp.reg());
 | 
| -        __ or_(Operand(tmp.reg()), new_value.reg());
 | 
| -        __ test(tmp.reg(), Immediate(kSmiTagMask));
 | 
| -        tmp.Unuse();
 | 
| -        deferred->Branch(not_zero);
 | 
| -      } else {
 | 
| -        // Otherwise we test separately for overflow and smi tag.
 | 
| -        deferred->Branch(overflow);
 | 
| -        __ test(new_value.reg(), Immediate(kSmiTagMask));
 | 
| -        deferred->Branch(not_zero);
 | 
| -      }
 | 
| -      deferred->BindExit();
 | 
| +      // Otherwise we test separately for overflow and smi tag.
 | 
| +      deferred->Branch(overflow);
 | 
| +      __ test(new_value.reg(), Immediate(kSmiTagMask));
 | 
| +      deferred->Branch(not_zero);
 | 
|      }
 | 
| +    deferred->BindExit();
 | 
|  
 | 
|      // Postfix: store the old value in the allocated slot under the
 | 
|      // reference.
 | 
| @@ -6857,15 +6823,8 @@
 | 
|        overwrite_mode = OVERWRITE_RIGHT;
 | 
|      }
 | 
|  
 | 
| -    if (node->left()->IsTrivial()) {
 | 
| -      Load(node->right());
 | 
| -      Result right = frame_->Pop();
 | 
| -      frame_->Push(node->left());
 | 
| -      frame_->Push(&right);
 | 
| -    } else {
 | 
| -      Load(node->left());
 | 
| -      Load(node->right());
 | 
| -    }
 | 
| +    Load(node->left());
 | 
| +    Load(node->right());
 | 
|      GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
 | 
|    }
 | 
|  }
 | 
| @@ -7065,20 +7024,8 @@
 | 
|      default:
 | 
|        UNREACHABLE();
 | 
|    }
 | 
| -
 | 
| -  if (left->IsTrivial()) {
 | 
| -    if (!left_already_loaded) {
 | 
| -      Load(right);
 | 
| -      Result right_result = frame_->Pop();
 | 
| -      frame_->Push(left);
 | 
| -      frame_->Push(&right_result);
 | 
| -    } else {
 | 
| -      Load(right);
 | 
| -    }
 | 
| -  } else {
 | 
| -    if (!left_already_loaded) Load(left);
 | 
| -    Load(right);
 | 
| -  }
 | 
| +  if (!left_already_loaded) Load(left);
 | 
| +  Load(right);
 | 
|    Comparison(node, cc, strict, destination());
 | 
|  }
 | 
|  
 | 
| 
 |