Reviewers: Mads Ager,

Description:
ARM: Add multiplication to the type recording binary operation stub

Please review this at http://codereview.chromium.org/6391004/

SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/

Affected files:
  M     src/arm/code-stubs-arm.h
  M     src/arm/code-stubs-arm.cc
  M     src/arm/full-codegen-arm.cc


Index: src/arm/code-stubs-arm.cc
===================================================================
--- src/arm/code-stubs-arm.cc   (revision 6488)
+++ src/arm/code-stubs-arm.cc   (working copy)
@@ -2434,13 +2434,17 @@
 }


-void TypeRecordingBinaryOpStub::GenerateOptimisticSmiOperation(
+void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation(
     MacroAssembler* masm) {
   Register left = r1;
   Register right = r0;
+  Register scratch1 = r7;
+  Register scratch2 = r9;

   ASSERT(right.is(r0));
+  STATIC_ASSERT(kSmiTag == 0);

+  Label not_smi_result;
   switch (op_) {
     case Token::ADD:
       __ add(right, left, Operand(right), SetCC);  // Add optimistically.
@@ -2452,9 +2456,35 @@
       __ Ret(vc);
       __ sub(right, left, Operand(right));  // Revert optimistic subtract.
       break;
+    case Token::MUL:
+ // Remove tag from one of the operands. This way the multiplication result
+      // will be a smi if it fits the smi range.
+      __ SmiUntag(ip, right);
+      // Do multiplication
+      // scratch1 = lower 32 bits of ip * left.
+      // scratch2 = higher 32 bits of ip * left.
+      __ smull(scratch1, scratch2, left, ip);
+ // Check for overflowing the smi range - no overflow if higher 33 bits of
+      // the result are identical.
+      __ mov(ip, Operand(scratch1, ASR, 31));
+      __ cmp(ip, Operand(scratch2));
+      __ b(ne, &not_smi_result);
+      // Go slow on zero result to handle -0.
+      __ tst(scratch1, Operand(scratch1));
+      __ mov(right, Operand(scratch1), 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(scratch2, right, Operand(left), SetCC);
+      __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl);
+      __ Ret(pl);  // Return smi 0 if the non-zero one was positive.
+ // We fall through here if we multiplied a negative number with 0, because
+      // that would mean we should produce -0.
+      break;
     default:
       UNREACHABLE();
   }
+  __ bind(&not_smi_result);
 }


@@ -2467,6 +2497,9 @@
     case Token::SUB:
       __ vsub(d5, d6, d7);
       break;
+    case Token::MUL:
+      __ vmul(d5, d6, d7);
+      break;
     default:
       UNREACHABLE();
   }
@@ -2482,7 +2515,7 @@
     SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
   Label not_smis;

-  ASSERT(op_ == Token::ADD || op_ == Token::SUB);
+  ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);

   Register left = r1;
   Register right = r0;
@@ -2495,7 +2528,7 @@
   __ tst(scratch1, Operand(kSmiTagMask));
   __ b(ne, &not_smis);

-  GenerateOptimisticSmiOperation(masm);
+  GenerateSmiSmiOperation(masm);

// If heap number results are possible generate the result in an allocated
   // heap number.
@@ -2563,7 +2596,7 @@
 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
   Label not_smis, call_runtime;

-  ASSERT(op_ == Token::ADD || op_ == Token::SUB);
+  ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);

   if (result_type_ == TRBinaryOpIC::UNINITIALIZED ||
       result_type_ == TRBinaryOpIC::SMI) {
@@ -2595,7 +2628,7 @@


 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
-  ASSERT(op_ == Token::ADD || op_ == Token::SUB);
+  ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::SUB);

   ASSERT(operands_type_ == TRBinaryOpIC::INT32);

@@ -2604,7 +2637,7 @@


void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
-  ASSERT(op_ == Token::ADD || op_ == Token::SUB);
+  ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);

   Register scratch1 = r7;
   Register scratch2 = r9;
@@ -2684,7 +2717,7 @@


 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
-  ASSERT(op_ == Token::ADD || op_ == Token::SUB);
+  ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);

   Label call_runtime;

Index: src/arm/code-stubs-arm.h
===================================================================
--- src/arm/code-stubs-arm.h    (revision 6488)
+++ src/arm/code-stubs-arm.h    (working copy)
@@ -288,7 +288,7 @@

   void Generate(MacroAssembler* masm);
   void GenerateGeneric(MacroAssembler* masm);
-  void GenerateOptimisticSmiOperation(MacroAssembler* masm);
+  void GenerateSmiSmiOperation(MacroAssembler* masm);
   void GenerateVFPOperation(MacroAssembler* masm);
   void GenerateSmiCode(MacroAssembler* masm,
                        Label* gc_required,
Index: src/arm/full-codegen-arm.cc
===================================================================
--- src/arm/full-codegen-arm.cc (revision 6488)
+++ src/arm/full-codegen-arm.cc (working copy)
@@ -1548,7 +1548,7 @@
 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
                                      OverwriteMode mode) {
   __ pop(r1);
-  if (op == Token::ADD || op == Token::SUB) {
+  if (op == Token::ADD || op == Token::SUB || op == Token::MUL) {
     TypeRecordingBinaryOpStub stub(op, mode);
     __ CallStub(&stub);
   } else {


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to