Revert change 4201.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 22 Mar 2010 12:16:11 +0000 (12:16 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 22 Mar 2010 12:16:11 +0000 (12:16 +0000)
Review URL: http://codereview.chromium.org/1113007

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

src/arm/codegen-arm.cc
src/arm/codegen-arm.h

index 67551e2dcd9aac5a23a4ab336e7ff42b8584e39f..d3e98a31090a07ee1272b83302f4e962aa9f6e35 100644 (file)
@@ -5523,212 +5523,45 @@ static void AllocateHeapNumber(
 // to call the C-implemented binary fp operation routines we need to end up
 // with the double precision floating point operands in r0 and r1 (for the
 // value in r1) and r2 and r3 (for the value in r0).
-void GenericBinaryOpStub::HandleBinaryOpSlowCases(MacroAssembler* masm,
+static void HandleBinaryOpSlowCases(MacroAssembler* masm,
                                     Label* not_smi,
-                                    const Builtins::JavaScript& builtin) {
+                                    const Builtins::JavaScript& builtin,
+                                    Token::Value operation,
+                                    OverwriteMode mode) {
   Label slow, slow_pop_2_first, do_the_call;
   Label r0_is_smi, r1_is_smi, finished_loading_r0, finished_loading_r1;
+  // Smi-smi case (overflow).
+  // Since both are Smis there is no heap number to overwrite, so allocate.
+  // The new heap number is in r5.  r6 and r7 are scratch.
+  AllocateHeapNumber(masm, &slow, r5, r6, r7);
+
   // If we have floating point hardware, inline ADD, SUB, MUL, and DIV,
   // using registers d7 and d6 for the double values.
   bool use_fp_registers = CpuFeatures::IsSupported(VFP3) &&
-      Token::MOD != op_;
-
-  if (ShouldGenerateSmiCode()) {
-    // Smi-smi case (overflow).
-    // Since both are Smis there is no heap number to overwrite, so allocate.
-    // The new heap number is in r5.  r6 and r7 are scratch.
-    AllocateHeapNumber(masm, &slow, r5, r6, r7);
-
-    if (use_fp_registers) {
-      CpuFeatures::Scope scope(VFP3);
-      __ mov(r7, Operand(r0, ASR, kSmiTagSize));
-      __ vmov(s15, r7);
-      __ vcvt(d7, s15);
-      __ mov(r7, Operand(r1, ASR, kSmiTagSize));
-      __ vmov(s13, r7);
-      __ vcvt(d6, s13);
-    } else {
-      // Write Smi from r0 to r3 and r2 in double format.  r6 is scratch.
-      __ mov(r7, Operand(r0));
-      ConvertToDoubleStub stub1(r3, r2, r7, r6);
-      __ push(lr);
-      __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
-      // Write Smi from r1 to r1 and r0 in double format.  r6 is scratch.
-      __ mov(r7, Operand(r1));
-      ConvertToDoubleStub stub2(r1, r0, r7, r6);
-      __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
-      __ pop(lr);
-    }
-
-    __ jmp(&do_the_call);  // Tail call.  No return.
+      Token::MOD != operation;
+  if (use_fp_registers) {
+    CpuFeatures::Scope scope(VFP3);
+    __ mov(r7, Operand(r0, ASR, kSmiTagSize));
+    __ vmov(s15, r7);
+    __ vcvt(d7, s15);
+    __ mov(r7, Operand(r1, ASR, kSmiTagSize));
+    __ vmov(s13, r7);
+    __ vcvt(d6, s13);
+  } else {
+    // Write Smi from r0 to r3 and r2 in double format.  r6 is scratch.
+    __ mov(r7, Operand(r0));
+    ConvertToDoubleStub stub1(r3, r2, r7, r6);
+    __ push(lr);
+    __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
+    // Write Smi from r1 to r1 and r0 in double format.  r6 is scratch.
+    __ mov(r7, Operand(r1));
+    ConvertToDoubleStub stub2(r1, r0, r7, r6);
+    __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
+    __ pop(lr);
   }
 
-  // We branch here if at least one of r0 and r1 is not a Smi.
-  __ bind(not_smi);
-
-  if (ShouldGenerateFPCode()) {
-    if (runtime_operands_type_ == BinaryOpIC::DEFAULT) {
-      switch (op_) {
-        case Token::ADD:
-        case Token::SUB:
-        case Token::MUL:
-        case Token::DIV:
-          GenerateTypeTransition(masm);
-          break;
-
-        default:
-          break;
-      }
-    }
-
-    if (mode_ == NO_OVERWRITE) {
-      // In the case where there is no chance of an overwritable float we may as
-      // well do the allocation immediately while r0 and r1 are untouched.
-      AllocateHeapNumber(masm, &slow, r5, r6, r7);
-    }
-
-    // Move r0 to a double in r2-r3.
-    __ tst(r0, Operand(kSmiTagMask));
-    __ b(eq, &r0_is_smi);  // It's a Smi so don't check it's a heap number.
-    __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
-    __ b(ne, &slow);
-    if (mode_ == OVERWRITE_RIGHT) {
-      __ mov(r5, Operand(r0));  // Overwrite this heap number.
-    }
-    if (use_fp_registers) {
-      CpuFeatures::Scope scope(VFP3);
-      // Load the double from tagged HeapNumber r0 to d7.
-      __ sub(r7, r0, Operand(kHeapObjectTag));
-      __ vldr(d7, r7, HeapNumber::kValueOffset);
-    } else {
-      // Calling convention says that second double is in r2 and r3.
-      __ ldr(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
-      __ ldr(r3, FieldMemOperand(r0, HeapNumber::kValueOffset + 4));
-    }
-    __ jmp(&finished_loading_r0);
-    __ bind(&r0_is_smi);
-    if (mode_ == OVERWRITE_RIGHT) {
-      // We can't overwrite a Smi so get address of new heap number into r5.
-      AllocateHeapNumber(masm, &slow, r5, r6, r7);
-    }
-
-    if (use_fp_registers) {
-      CpuFeatures::Scope scope(VFP3);
-      // Convert smi in r0 to double in d7.
-      __ mov(r7, Operand(r0, ASR, kSmiTagSize));
-      __ vmov(s15, r7);
-      __ vcvt(d7, s15);
-    } else {
-      // Write Smi from r0 to r3 and r2 in double format.
-      __ mov(r7, Operand(r0));
-      ConvertToDoubleStub stub3(r3, r2, r7, r6);
-      __ push(lr);
-      __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET);
-      __ pop(lr);
-    }
-
-    __ bind(&finished_loading_r0);
-
-    // Move r1 to a double in r0-r1.
-    __ tst(r1, Operand(kSmiTagMask));
-    __ b(eq, &r1_is_smi);  // It's a Smi so don't check it's a heap number.
-    __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
-    __ b(ne, &slow);
-    if (mode_ == OVERWRITE_LEFT) {
-      __ mov(r5, Operand(r1));  // Overwrite this heap number.
-    }
-    if (use_fp_registers) {
-      CpuFeatures::Scope scope(VFP3);
-      // Load the double from tagged HeapNumber r1 to d6.
-      __ sub(r7, r1, Operand(kHeapObjectTag));
-      __ vldr(d6, r7, HeapNumber::kValueOffset);
-    } else {
-      // Calling convention says that first double is in r0 and r1.
-      __ ldr(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
-      __ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + 4));
-    }
-    __ jmp(&finished_loading_r1);
-    __ bind(&r1_is_smi);
-    if (mode_ == OVERWRITE_LEFT) {
-      // We can't overwrite a Smi so get address of new heap number into r5.
-      AllocateHeapNumber(masm, &slow, r5, r6, r7);
-    }
-
-    if (use_fp_registers) {
-      CpuFeatures::Scope scope(VFP3);
-      // Convert smi in r1 to double in d6.
-      __ mov(r7, Operand(r1, ASR, kSmiTagSize));
-      __ vmov(s13, r7);
-      __ vcvt(d6, s13);
-    } else {
-      // Write Smi from r1 to r1 and r0 in double format.
-      __ mov(r7, Operand(r1));
-      ConvertToDoubleStub stub4(r1, r0, r7, r6);
-      __ push(lr);
-      __ Call(stub4.GetCode(), RelocInfo::CODE_TARGET);
-      __ pop(lr);
-    }
+  __ jmp(&do_the_call);  // Tail call.  No return.
 
-    __ bind(&finished_loading_r1);
-
-    __ bind(&do_the_call);
-    // If we are inlining the operation using VFP3 instructions for
-    // add, subtract, multiply, or divide, the arguments are in d6 and d7.
-    if (use_fp_registers) {
-      CpuFeatures::Scope scope(VFP3);
-      // ARMv7 VFP3 instructions to implement
-      // double precision, add, subtract, multiply, divide.
-
-      if (Token::MUL == op_) {
-        __ vmul(d5, d6, d7);
-      } else if (Token::DIV == op_) {
-        __ vdiv(d5, d6, d7);
-      } else if (Token::ADD == op_) {
-        __ vadd(d5, d6, d7);
-      } else if (Token::SUB == op_) {
-        __ vsub(d5, d6, d7);
-      } else {
-        UNREACHABLE();
-      }
-      __ sub(r0, r5, Operand(kHeapObjectTag));
-      __ vstr(d5, r0, HeapNumber::kValueOffset);
-      __ add(r0, r0, Operand(kHeapObjectTag));
-      __ mov(pc, lr);
-    } else {
-      // If we did not inline the operation, then the arguments are in:
-      // r0: Left value (least significant part of mantissa).
-      // r1: Left value (sign, exponent, top of mantissa).
-      // r2: Right value (least significant part of mantissa).
-      // r3: Right value (sign, exponent, top of mantissa).
-      // r5: Address of heap number for result.
-
-      __ push(lr);   // For later.
-      __ push(r5);   // Address of heap number that is answer.
-      __ AlignStack(0);
-      // Call C routine that may not cause GC or other trouble.
-      __ mov(r5, Operand(ExternalReference::double_fp_operation(op_)));
-      __ Call(r5);
-      __ pop(r4);  // Address of heap number.
-      __ cmp(r4, Operand(Smi::FromInt(0)));
-      __ pop(r4, eq);  // Conditional pop instruction
-                       // to get rid of alignment push.
-      // Store answer in the overwritable heap number.
-  #if !defined(USE_ARM_EABI)
-      // Double returned in fp coprocessor register 0 and 1, encoded as register
-      // cr8.  Offsets must be divisible by 4 for coprocessor so we need to
-      // substract the tag from r4.
-      __ sub(r5, r4, Operand(kHeapObjectTag));
-      __ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset));
-  #else
-      // Double returned in registers 0 and 1.
-      __ str(r0, FieldMemOperand(r4, HeapNumber::kValueOffset));
-      __ str(r1, FieldMemOperand(r4, HeapNumber::kValueOffset + 4));
-  #endif
-      __ mov(r0, Operand(r4));
-      // And we are done.
-      __ pop(pc);
-    }
-  }
   // We jump to here if something goes wrong (one param is not a number of any
   // sort or new-space allocation fails).
   __ bind(&slow);
@@ -5737,7 +5570,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(MacroAssembler* masm,
   __ push(r1);
   __ push(r0);
 
-  if (Token::ADD == op_) {
+  if (Token::ADD == operation) {
     // Test for string arguments before calling runtime.
     // r1 : first argument
     // r0 : second argument
@@ -5789,6 +5622,156 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(MacroAssembler* masm,
   }
 
   __ InvokeBuiltin(builtin, JUMP_JS);  // Tail call.  No return.
+
+  // We branch here if at least one of r0 and r1 is not a Smi.
+  __ bind(not_smi);
+  if (mode == NO_OVERWRITE) {
+    // In the case where there is no chance of an overwritable float we may as
+    // well do the allocation immediately while r0 and r1 are untouched.
+    AllocateHeapNumber(masm, &slow, r5, r6, r7);
+  }
+
+  // Move r0 to a double in r2-r3.
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(eq, &r0_is_smi);  // It's a Smi so don't check it's a heap number.
+  __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
+  __ b(ne, &slow);
+  if (mode == OVERWRITE_RIGHT) {
+    __ mov(r5, Operand(r0));  // Overwrite this heap number.
+  }
+  if (use_fp_registers) {
+    CpuFeatures::Scope scope(VFP3);
+    // Load the double from tagged HeapNumber r0 to d7.
+    __ sub(r7, r0, Operand(kHeapObjectTag));
+    __ vldr(d7, r7, HeapNumber::kValueOffset);
+  } else {
+    // Calling convention says that second double is in r2 and r3.
+    __ ldr(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ ldr(r3, FieldMemOperand(r0, HeapNumber::kValueOffset + 4));
+  }
+  __ jmp(&finished_loading_r0);
+  __ bind(&r0_is_smi);
+  if (mode == OVERWRITE_RIGHT) {
+    // We can't overwrite a Smi so get address of new heap number into r5.
+    AllocateHeapNumber(masm, &slow, r5, r6, r7);
+  }
+
+  if (use_fp_registers) {
+    CpuFeatures::Scope scope(VFP3);
+    // Convert smi in r0 to double in d7.
+    __ mov(r7, Operand(r0, ASR, kSmiTagSize));
+    __ vmov(s15, r7);
+    __ vcvt(d7, s15);
+  } else {
+    // Write Smi from r0 to r3 and r2 in double format.
+    __ mov(r7, Operand(r0));
+    ConvertToDoubleStub stub3(r3, r2, r7, r6);
+    __ push(lr);
+    __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET);
+    __ pop(lr);
+  }
+
+  __ bind(&finished_loading_r0);
+
+  // Move r1 to a double in r0-r1.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &r1_is_smi);  // It's a Smi so don't check it's a heap number.
+  __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
+  __ b(ne, &slow);
+  if (mode == OVERWRITE_LEFT) {
+    __ mov(r5, Operand(r1));  // Overwrite this heap number.
+  }
+  if (use_fp_registers) {
+    CpuFeatures::Scope scope(VFP3);
+    // Load the double from tagged HeapNumber r1 to d6.
+    __ sub(r7, r1, Operand(kHeapObjectTag));
+    __ vldr(d6, r7, HeapNumber::kValueOffset);
+  } else {
+    // Calling convention says that first double is in r0 and r1.
+    __ ldr(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + 4));
+  }
+  __ jmp(&finished_loading_r1);
+  __ bind(&r1_is_smi);
+  if (mode == OVERWRITE_LEFT) {
+    // We can't overwrite a Smi so get address of new heap number into r5.
+    AllocateHeapNumber(masm, &slow, r5, r6, r7);
+  }
+
+  if (use_fp_registers) {
+    CpuFeatures::Scope scope(VFP3);
+    // Convert smi in r1 to double in d6.
+    __ mov(r7, Operand(r1, ASR, kSmiTagSize));
+    __ vmov(s13, r7);
+    __ vcvt(d6, s13);
+  } else {
+    // Write Smi from r1 to r1 and r0 in double format.
+    __ mov(r7, Operand(r1));
+    ConvertToDoubleStub stub4(r1, r0, r7, r6);
+    __ push(lr);
+    __ Call(stub4.GetCode(), RelocInfo::CODE_TARGET);
+    __ pop(lr);
+  }
+
+  __ bind(&finished_loading_r1);
+
+  __ bind(&do_the_call);
+  // If we are inlining the operation using VFP3 instructions for
+  // add, subtract, multiply, or divide, the arguments are in d6 and d7.
+  if (use_fp_registers) {
+    CpuFeatures::Scope scope(VFP3);
+    // ARMv7 VFP3 instructions to implement
+    // double precision, add, subtract, multiply, divide.
+
+    if (Token::MUL == operation) {
+      __ vmul(d5, d6, d7);
+    } else if (Token::DIV == operation) {
+      __ vdiv(d5, d6, d7);
+    } else if (Token::ADD == operation) {
+      __ vadd(d5, d6, d7);
+    } else if (Token::SUB == operation) {
+      __ vsub(d5, d6, d7);
+    } else {
+      UNREACHABLE();
+    }
+    __ sub(r0, r5, Operand(kHeapObjectTag));
+    __ vstr(d5, r0, HeapNumber::kValueOffset);
+    __ add(r0, r0, Operand(kHeapObjectTag));
+    __ mov(pc, lr);
+    return;
+  }
+
+  // If we did not inline the operation, then the arguments are in:
+  // r0: Left value (least significant part of mantissa).
+  // r1: Left value (sign, exponent, top of mantissa).
+  // r2: Right value (least significant part of mantissa).
+  // r3: Right value (sign, exponent, top of mantissa).
+  // r5: Address of heap number for result.
+
+  __ push(lr);   // For later.
+  __ push(r5);   // Address of heap number that is answer.
+  __ AlignStack(0);
+  // Call C routine that may not cause GC or other trouble.
+  __ mov(r5, Operand(ExternalReference::double_fp_operation(operation)));
+  __ Call(r5);
+  __ pop(r4);  // Address of heap number.
+  __ cmp(r4, Operand(Smi::FromInt(0)));
+  __ pop(r4, eq);  // Conditional pop instruction to get rid of alignment push.
+  // Store answer in the overwritable heap number.
+#if !defined(USE_ARM_EABI)
+  // Double returned in fp coprocessor register 0 and 1, encoded as register
+  // cr8.  Offsets must be divisible by 4 for coprocessor so we need to
+  // substract the tag from r4.
+  __ sub(r5, r4, Operand(kHeapObjectTag));
+  __ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset));
+#else
+  // Double returned in registers 0 and 1.
+  __ str(r0, FieldMemOperand(r4, HeapNumber::kValueOffset));
+  __ str(r1, FieldMemOperand(r4, HeapNumber::kValueOffset + 4));
+#endif
+  __ mov(r0, Operand(r4));
+  // And we are done.
+  __ pop(pc);
 }
 
 
@@ -6122,78 +6105,85 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
 
   // All ops need to know whether we are dealing with two Smis.  Set up r2 to
   // tell us that.
-  if (ShouldGenerateSmiCode()) {
-    __ orr(r2, r1, Operand(r0));  // r2 = x | y;
-  }
+  __ orr(r2, r1, Operand(r0));  // r2 = x | y;
 
   switch (op_) {
     case Token::ADD: {
       Label not_smi;
       // Fast path.
-      if (ShouldGenerateSmiCode()) {
-        ASSERT(kSmiTag == 0);  // Adjust code below.
-        __ tst(r2, Operand(kSmiTagMask));
-        __ b(ne, &not_smi);
-        __ add(r0, r1, Operand(r0), SetCC);  // Add y optimistically.
-        // Return if no overflow.
-        __ Ret(vc);
-        __ sub(r0, r0, Operand(r1));  // Revert optimistic add.
-      }
-      HandleBinaryOpSlowCases(masm, &not_smi, Builtins::ADD);
+      ASSERT(kSmiTag == 0);  // Adjust code below.
+      __ tst(r2, Operand(kSmiTagMask));
+      __ b(ne, &not_smi);
+      __ add(r0, r1, Operand(r0), SetCC);  // Add y optimistically.
+      // Return if no overflow.
+      __ Ret(vc);
+      __ sub(r0, r0, Operand(r1));  // Revert optimistic add.
+
+      HandleBinaryOpSlowCases(masm,
+                              &not_smi,
+                              Builtins::ADD,
+                              Token::ADD,
+                              mode_);
       break;
     }
 
     case Token::SUB: {
       Label not_smi;
       // Fast path.
-      if (ShouldGenerateSmiCode()) {
-        ASSERT(kSmiTag == 0);  // Adjust code below.
-        __ tst(r2, Operand(kSmiTagMask));
-        __ b(ne, &not_smi);
-        __ sub(r0, r1, Operand(r0), SetCC);  // Subtract y optimistically.
-        // Return if no overflow.
-        __ Ret(vc);
-        __ sub(r0, r1, Operand(r0));  // Revert optimistic subtract.
-      }
-      HandleBinaryOpSlowCases(masm, &not_smi, Builtins::SUB);
+      ASSERT(kSmiTag == 0);  // Adjust code below.
+      __ tst(r2, Operand(kSmiTagMask));
+      __ b(ne, &not_smi);
+      __ sub(r0, r1, Operand(r0), SetCC);  // Subtract y optimistically.
+      // Return if no overflow.
+      __ Ret(vc);
+      __ sub(r0, r1, Operand(r0));  // Revert optimistic subtract.
+
+      HandleBinaryOpSlowCases(masm,
+                              &not_smi,
+                              Builtins::SUB,
+                              Token::SUB,
+                              mode_);
       break;
     }
 
     case Token::MUL: {
       Label not_smi, slow;
-      if (ShouldGenerateSmiCode()) {
-        ASSERT(kSmiTag == 0);  // adjust code below
-        __ tst(r2, Operand(kSmiTagMask));
-        __ b(ne, &not_smi);
-        // Remove tag from one operand (but keep sign), so that result is Smi.
-        __ mov(ip, Operand(r0, ASR, kSmiTagSize));
-        // Do multiplication
-        __ smull(r3, r2, r1, ip);  // r3 = lower 32 bits of ip*r1.
-        // Go slow on overflows (overflow bit is not set).
-        __ mov(ip, Operand(r3, ASR, 31));
-        __ cmp(ip, Operand(r2));  // no overflow if higher 33 bits are identical
-        __ b(ne, &slow);
-        // Go slow on zero result to handle -0.
-        __ tst(r3, Operand(r3));
-        __ mov(r0, Operand(r3), LeaveCC, ne);
-        __ Ret(ne);
-        // We need -0 if we were multiplying a negative number with 0 to get 0.
-        // We know one of them was zero.
-        __ add(r2, r0, Operand(r1), SetCC);
-        __ mov(r0, Operand(Smi::FromInt(0)), LeaveCC, pl);
-        __ Ret(pl);  // Return Smi 0 if the non-zero one was positive.
-        // Slow case.  We fall through here if we multiplied a negative number
-        // with 0, because that would mean we should produce -0.
-        __ bind(&slow);
-      }
-      HandleBinaryOpSlowCases(masm, &not_smi, Builtins::MUL);
+      ASSERT(kSmiTag == 0);  // adjust code below
+      __ tst(r2, Operand(kSmiTagMask));
+      __ b(ne, &not_smi);
+      // Remove tag from one operand (but keep sign), so that result is Smi.
+      __ mov(ip, Operand(r0, ASR, kSmiTagSize));
+      // Do multiplication
+      __ smull(r3, r2, r1, ip);  // r3 = lower 32 bits of ip*r1.
+      // Go slow on overflows (overflow bit is not set).
+      __ mov(ip, Operand(r3, ASR, 31));
+      __ cmp(ip, Operand(r2));  // no overflow if higher 33 bits are identical
+      __ b(ne, &slow);
+      // Go slow on zero result to handle -0.
+      __ tst(r3, Operand(r3));
+      __ mov(r0, Operand(r3), LeaveCC, ne);
+      __ Ret(ne);
+      // We need -0 if we were multiplying a negative number with 0 to get 0.
+      // We know one of them was zero.
+      __ add(r2, r0, Operand(r1), SetCC);
+      __ mov(r0, Operand(Smi::FromInt(0)), LeaveCC, pl);
+      __ Ret(pl);  // Return Smi 0 if the non-zero one was positive.
+      // Slow case.  We fall through here if we multiplied a negative number
+      // with 0, because that would mean we should produce -0.
+      __ bind(&slow);
+
+      HandleBinaryOpSlowCases(masm,
+                              &not_smi,
+                              Builtins::MUL,
+                              Token::MUL,
+                              mode_);
       break;
     }
 
     case Token::DIV:
     case Token::MOD: {
       Label not_smi;
-      if (ShouldGenerateSmiCode()) {
+      if (specialized_on_rhs_) {
         Label smi_is_unsuitable;
         __ BranchOnNotSmi(r1, &not_smi);
         if (IsPowerOf2(constant_rhs_)) {
@@ -6273,11 +6263,14 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
         }
         __ Ret();
         __ bind(&smi_is_unsuitable);
+      } else {
+        __ jmp(&not_smi);
       }
-      HandleBinaryOpSlowCases(
-          masm,
-          &not_smi,
-          op_ == Token::MOD ? Builtins::MOD : Builtins::DIV);
+      HandleBinaryOpSlowCases(masm,
+                              &not_smi,
+                              op_ == Token::MOD ? Builtins::MOD : Builtins::DIV,
+                              op_,
+                              mode_);
       break;
     }
 
@@ -6337,52 +6330,11 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
   }
   // This code should be unreachable.
   __ stop("Unreachable");
-
-  // Generate an unreachable reference to the DEFAULT stub so that it can be
-  // found at the end of this stub when clearing ICs at GC.
-  // TODO(kaznacheev): Check performance impact and get rid of this.
-  if (runtime_operands_type_ != BinaryOpIC::DEFAULT) {
-    GenericBinaryOpStub uninit(MinorKey(), BinaryOpIC::DEFAULT);
-    __ CallStub(&uninit);
-  }
-}
-
-
-void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
-  Label get_result;
-
-  __ push(r1);
-  __ push(r0);
-
-  // Internal frame is necessary to handle exceptions properly.
-  __ EnterInternalFrame();
-  // Call the stub proper to get the result in r0.
-  __ Call(&get_result);
-  __ LeaveInternalFrame();
-
-  __ push(r0);
-
-  __ mov(r0, Operand(Smi::FromInt(MinorKey())));
-  __ push(r0);
-  __ mov(r0, Operand(Smi::FromInt(op_)));
-  __ push(r0);
-  __ mov(r0, Operand(Smi::FromInt(runtime_operands_type_)));
-  __ push(r0);
-
-  __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
-      6,
-      1);
-
-  // The entry point for the result calculation is assumed to be immediately
-  // after this sequence.
-  __ bind(&get_result);
 }
 
 
 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
-  GenericBinaryOpStub stub(key, type_info);
-  return stub.GetCode();
+  return Handle<Code>::null();
 }
 
 
index 8abfe10b7f7854605afeea3a32575243b2654f24..68f293a853b049d721101b9e7484642c522b9abe 100644 (file)
@@ -28,8 +28,6 @@
 #ifndef V8_ARM_CODEGEN_ARM_H_
 #define V8_ARM_CODEGEN_ARM_H_
 
-#include "ic-inl.h"
-
 namespace v8 {
 namespace internal {
 
@@ -474,15 +472,6 @@ class GenericBinaryOpStub : public CodeStub {
         mode_(mode),
         constant_rhs_(constant_rhs),
         specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
-        runtime_operands_type_(BinaryOpIC::DEFAULT),
-        name_(NULL) { }
-
-  GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
-      : op_(OpBits::decode(key)),
-        mode_(ModeBits::decode(key)),
-        constant_rhs_(KnownBitsForMinorKey(KnownIntBits::decode(key))),
-        specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op_, constant_rhs_)),
-        runtime_operands_type_(type_info),
         name_(NULL) { }
 
  private:
@@ -490,32 +479,25 @@ class GenericBinaryOpStub : public CodeStub {
   OverwriteMode mode_;
   int constant_rhs_;
   bool specialized_on_rhs_;
-  BinaryOpIC::TypeInfo runtime_operands_type_;
   char* name_;
 
   static const int kMaxKnownRhs = 0x40000000;
 
-  // Minor key encoding in 18 bits.
+  // Minor key encoding in 16 bits.
   class ModeBits: public BitField<OverwriteMode, 0, 2> {};
   class OpBits: public BitField<Token::Value, 2, 6> {};
   class KnownIntBits: public BitField<int, 8, 8> {};
-  class TypeInfoBits: public BitField<int, 16, 2> {};
 
   Major MajorKey() { return GenericBinaryOp; }
   int MinorKey() {
-    // Encode the parameters in a unique 18 bit value.
+    // Encode the parameters in a unique 16 bit value.
     return OpBits::encode(op_)
            | ModeBits::encode(mode_)
-           | KnownIntBits::encode(MinorKeyForKnownInt())
-           | TypeInfoBits::encode(runtime_operands_type_);
+           | KnownIntBits::encode(MinorKeyForKnownInt());
   }
 
   void Generate(MacroAssembler* masm);
   void HandleNonSmiBitwiseOp(MacroAssembler* masm);
-  void HandleBinaryOpSlowCases(MacroAssembler* masm,
-                               Label* not_smi,
-                               const Builtins::JavaScript& builtin);
-  void GenerateTypeTransition(MacroAssembler* masm);
 
   static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) {
     if (constant_rhs == CodeGenerator::kUnknownIntValue) return false;
@@ -542,33 +524,6 @@ class GenericBinaryOpStub : public CodeStub {
     return key;
   }
 
-  int KnownBitsForMinorKey(int key) {
-    if (!key) return 0;
-    if (key <= 11) return key - 1;
-    int d = 1;
-    while (key != 12) {
-      key--;
-      d <<= 1;
-    }
-    return d;
-  }
-
-  bool ShouldGenerateSmiCode() {
-    return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) &&
-        runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
-        runtime_operands_type_ != BinaryOpIC::STRINGS;
-  }
-
-  bool ShouldGenerateFPCode() {
-    return runtime_operands_type_ != BinaryOpIC::STRINGS;
-  }
-
-  virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
-
-  virtual InlineCacheState GetICState() {
-    return BinaryOpIC::ToState(runtime_operands_type_);
-  }
-
   const char* GetName();
 
 #ifdef DEBUG