Revision: 16461
Author:   [email protected]
Date:     Sun Sep  1 17:22:08 2013 UTC
Log:      MIPS: Support for DoubleToIStub (truncating).

Port r16322 (8a03070)

Original commit message:
Added support for truncating DoubleToIStub and reorganize the macro-assembler
dToI operations to do the fast-path inline and the slow path by calling the
stub.

BUG=
[email protected]

Review URL: https://codereview.chromium.org/23694014

Patch from Balazs Kilvady <[email protected]>.
http://code.google.com/p/v8/source/detail?r=16461

Modified:
 /branches/bleeding_edge/src/mips/code-stubs-mips.cc
 /branches/bleeding_edge/src/mips/code-stubs-mips.h
 /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
 /branches/bleeding_edge/src/mips/lithium-mips.cc
 /branches/bleeding_edge/src/mips/lithium-mips.h
 /branches/bleeding_edge/src/mips/macro-assembler-mips.cc
 /branches/bleeding_edge/src/mips/macro-assembler-mips.h

=======================================
--- /branches/bleeding_edge/src/mips/code-stubs-mips.cc Fri Aug 30 11:24:58 2013 UTC +++ /branches/bleeding_edge/src/mips/code-stubs-mips.cc Sun Sep 1 17:22:08 2013 UTC
@@ -519,6 +519,64 @@
   __ Ret(USE_DELAY_SLOT);
   __ or_(exponent, exponent, source_);
 }
+
+
+void DoubleToIStub::Generate(MacroAssembler* masm) {
+  Label out_of_range, only_low, negate, done;
+  Register input_reg = source();
+  Register result_reg = destination();
+
+  int double_offset = offset();
+  // Account for saved regs if input is sp.
+  if (input_reg.is(sp)) double_offset += 3 * kPointerSize;
+
+  Register scratch =
+      GetRegisterThatIsNotOneOf(input_reg, result_reg);
+  Register scratch2 =
+      GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
+  Register scratch3 =
+      GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch2);
+  DoubleRegister double_scratch = kLithiumScratchDouble.low();
+  DoubleRegister double_input = f12;
+
+  __ Push(scratch, scratch2, scratch3);
+
+  __ ldc1(double_input, MemOperand(input_reg, double_offset));
+
+  if (!skip_fastpath()) {
+    // Clear cumulative exception flags and save the FCSR.
+    __ cfc1(scratch2, FCSR);
+    __ ctc1(zero_reg, FCSR);
+    // Try a conversion to a signed integer.
+    __ trunc_w_d(double_scratch, double_input);
+    __ mfc1(result_reg, double_scratch);
+    // Retrieve and restore the FCSR.
+    __ cfc1(scratch, FCSR);
+    __ ctc1(scratch2, FCSR);
+    // Check for overflow and NaNs.
+    __ And(
+        scratch, scratch,
+        kFCSROverflowFlagMask | kFCSRUnderflowFlagMask
+           | kFCSRInvalidOpFlagMask);
+    // If we had no exceptions we are done.
+    __ Branch(&done, eq, scratch, Operand(zero_reg));
+  }
+
+  // Load the double value and perform a manual truncation.
+  Register input_high = scratch2;
+  Register input_low = scratch3;
+  __ Move(input_low, input_high, double_input);
+
+  __ EmitOutOfInt32RangeTruncate(result_reg,
+                                 input_high,
+                                 input_low,
+                                 scratch);
+
+  __ bind(&done);
+
+  __ Pop(scratch, scratch2, scratch3);
+  __ Ret();
+}


 bool WriteInt32ToHeapNumberStub::IsPregenerated() {
@@ -1532,12 +1590,12 @@
         __ SmiUntag(a2, right);
       } else {
         // Convert operands to 32-bit integers. Right in a2 and left in a3.
-        __ ConvertNumberToInt32(
+        __ TruncateNumberToI(
             left, a3, heap_number_map,
-            scratch1, scratch2, scratch3, f0, not_numbers);
-        __ ConvertNumberToInt32(
+            scratch1, scratch2, scratch3, not_numbers);
+        __ TruncateNumberToI(
             right, a2, heap_number_map,
-            scratch1, scratch2, scratch3, f0, not_numbers);
+            scratch1, scratch2, scratch3, not_numbers);
       }
       Label result_not_a_smi;
       switch (op) {
=======================================
--- /branches/bleeding_edge/src/mips/code-stubs-mips.h Thu Aug 29 03:29:24 2013 UTC +++ /branches/bleeding_edge/src/mips/code-stubs-mips.h Sun Sep 1 17:22:08 2013 UTC
@@ -391,7 +391,7 @@
           address_(address),
           scratch0_(scratch0) {
       ASSERT(!AreAliased(scratch0, object, address, no_reg));
-      scratch1_ = GetRegThatIsNotOneOf(object_, address_, scratch0_);
+      scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_);
     }

     void Save(MacroAssembler* masm) {
@@ -434,19 +434,6 @@
     Register scratch0_;
     Register scratch1_;

-    Register GetRegThatIsNotOneOf(Register r1,
-                                  Register r2,
-                                  Register r3) {
-      for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
-        Register candidate = Register::FromAllocationIndex(i);
-        if (candidate.is(r1)) continue;
-        if (candidate.is(r2)) continue;
-        if (candidate.is(r3)) continue;
-        return candidate;
-      }
-      UNREACHABLE();
-      return no_reg;
-    }
     friend class RecordWriteStub;
   };

=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Fri Aug 30 11:24:58 2013 UTC +++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Sun Sep 1 17:22:08 2013 UTC
@@ -4853,7 +4853,7 @@
   Register scratch1 = scratch0();
   Register scratch2 = ToRegister(instr->temp());
   DoubleRegister double_scratch = double_scratch0();
-  DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp3());
+  DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2());

   ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
   ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
@@ -4868,11 +4868,6 @@
   // of the if.

   if (instr->truncating()) {
-    Register scratch3 = ToRegister(instr->temp2());
-    FPURegister single_scratch = double_scratch.low();
-    ASSERT(!scratch3.is(input_reg) &&
-           !scratch3.is(scratch1) &&
-           !scratch3.is(scratch2));
// Performs a truncating conversion of a floating point number as used by
     // the JS bitwise operations.
     Label heap_number;
@@ -4886,14 +4881,8 @@
     __ Branch(&done);

     __ bind(&heap_number);
-    __ ldc1(double_scratch2,
-            FieldMemOperand(input_reg, HeapNumber::kValueOffset));
-    __ EmitECMATruncate(input_reg,
-                        double_scratch2,
-                        single_scratch,
-                        scratch1,
-                        scratch2,
-                        scratch3);
+    __ mov(scratch2, input_reg);
+    __ TruncateHeapNumberToI(input_reg, scratch2);
   } else {
     // Deoptimize if we don't have a heap number.
     DeoptimizeIf(ne, instr->environment(), scratch1, Operand(at));
@@ -4980,20 +4969,12 @@
 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
   Register result_reg = ToRegister(instr->result());
   Register scratch1 = scratch0();
-  Register scratch2 = ToRegister(instr->temp());
   DoubleRegister double_input = ToDoubleRegister(instr->value());

   if (instr->truncating()) {
-    Register scratch3 = ToRegister(instr->temp2());
-    FPURegister single_scratch = double_scratch0().low();
-    __ EmitECMATruncate(result_reg,
-                        double_input,
-                        single_scratch,
-                        scratch1,
-                        scratch2,
-                        scratch3);
+    __ TruncateDoubleToI(result_reg, double_input);
   } else {
-    Register except_flag = scratch2;
+    Register except_flag = LCodeGen::scratch1();

     __ EmitFPUTruncate(kRoundToMinusInf,
                        result_reg,
@@ -5020,21 +5001,13 @@

 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
   Register result_reg = ToRegister(instr->result());
-  Register scratch1 = scratch0();
-  Register scratch2 = ToRegister(instr->temp());
+  Register scratch1 = LCodeGen::scratch0();
   DoubleRegister double_input = ToDoubleRegister(instr->value());

   if (instr->truncating()) {
-    Register scratch3 = ToRegister(instr->temp2());
-    FPURegister single_scratch = double_scratch0().low();
-    __ EmitECMATruncate(result_reg,
-                        double_input,
-                        single_scratch,
-                        scratch1,
-                        scratch2,
-                        scratch3);
+    __ TruncateDoubleToI(result_reg, double_input);
   } else {
-    Register except_flag = scratch2;
+    Register except_flag = LCodeGen::scratch1();

     __ EmitFPUTruncate(kRoundToMinusInf,
                        result_reg,
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.cc Wed Aug 28 15:00:30 2013 UTC +++ /branches/bleeding_edge/src/mips/lithium-mips.cc Sun Sep 1 17:22:08 2013 UTC
@@ -1844,13 +1844,10 @@
       } else {
         value = UseRegister(val);
         LOperand* temp1 = TempRegister();
-        LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
-                                                      : NULL;
-        LOperand* temp3 = FixedTemp(f22);
+        LOperand* temp2 = FixedTemp(f22);
         res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
                                                        temp1,
-                                                       temp2,
-                                                       temp3));
+                                                       temp2));
         res = AssignEnvironment(res);
       }
       return res;
@@ -1870,14 +1867,12 @@
       return AssignPointerMap(result);
     } else if (to.IsSmi()) {
       LOperand* value = UseRegister(instr->value());
- return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToSmi(value,
-          TempRegister(), TempRegister())));
+      return AssignEnvironment(
+          DefineAsRegister(new(zone()) LDoubleToSmi(value)));
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = UseRegister(instr->value());
-      LOperand* temp1 = TempRegister();
- LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
-      LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
+      LDoubleToI* res = new(zone()) LDoubleToI(value);
       return AssignEnvironment(DefineAsRegister(res));
     }
   } else if (from.IsInteger32()) {
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.h Wed Aug 28 14:16:57 2013 UTC +++ /branches/bleeding_edge/src/mips/lithium-mips.h Sun Sep 1 17:22:08 2013 UTC
@@ -2041,17 +2041,13 @@
 };


-class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 2> {
+class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
-  LDoubleToSmi(LOperand* value, LOperand* temp, LOperand* temp2) {
+  explicit LDoubleToSmi(LOperand* value) {
     inputs_[0] = value;
-    temps_[0] = temp;
-    temps_[1] = temp2;
   }

   LOperand* value() { return inputs_[0]; }
-  LOperand* temp() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }

   DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
@@ -2061,17 +2057,13 @@


 // Sometimes truncating conversion from a tagged value to an int32.
-class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
+class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
-  LDoubleToI(LOperand* value, LOperand* temp, LOperand* temp2) {
+  explicit LDoubleToI(LOperand* value) {
     inputs_[0] = value;
-    temps_[0] = temp;
-    temps_[1] = temp2;
   }

   LOperand* value() { return inputs_[0]; }
-  LOperand* temp() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }

   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
@@ -2081,22 +2073,19 @@


 // Truncating conversion from a tagged value to an int32.
-class LTaggedToI V8_FINAL : public LTemplateInstruction<1, 1, 3> {
+class LTaggedToI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
  public:
   LTaggedToI(LOperand* value,
              LOperand* temp,
-             LOperand* temp2,
-             LOperand* temp3) {
+             LOperand* temp2) {
     inputs_[0] = value;
     temps_[0] = temp;
     temps_[1] = temp2;
-    temps_[2] = temp3;
   }

   LOperand* value() { return inputs_[0]; }
   LOperand* temp() { return temps_[0]; }
   LOperand* temp2() { return temps_[1]; }
-  LOperand* temp3() { return temps_[2]; }

   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Thu Aug 29 03:29:24 2013 UTC +++ /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Sun Sep 1 17:22:08 2013 UTC
@@ -1498,22 +1498,12 @@
 }


-void MacroAssembler::EmitECMATruncate(Register result,
-                                      FPURegister double_input,
-                                      FPURegister single_scratch,
-                                      Register scratch,
-                                      Register scratch2,
-                                      Register scratch3) {
-  ASSERT(!scratch2.is(result));
-  ASSERT(!scratch3.is(result));
-  ASSERT(!scratch3.is(scratch2));
-  ASSERT(!scratch.is(result) &&
-         !scratch.is(scratch2) &&
-         !scratch.is(scratch3));
-  ASSERT(!single_scratch.is(double_input));
-
-  Label done;
-  Label manual;
+void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
+ DoubleRegister double_input,
+                                                Label* done) {
+  DoubleRegister single_scratch = kLithiumScratchDouble.low();
+  Register scratch = at;
+  Register scratch2 = t9;

   // Clear cumulative exception flags and save the FCSR.
   cfc1(scratch2, FCSR);
@@ -1529,16 +1519,83 @@
       scratch,
kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask);
   // If we had no exceptions we are done.
-  Branch(&done, eq, scratch, Operand(zero_reg));
+  Branch(done, eq, scratch, Operand(zero_reg));
+}
+
+
+void MacroAssembler::TruncateDoubleToI(Register result,
+                                       DoubleRegister double_input) {
+  Label done;
+
+  TryInlineTruncateDoubleToI(result, double_input, &done);
+
+ // If we fell through then inline version didn't succeed - call stub instead.
+  push(ra);
+  Subu(sp, sp, Operand(kDoubleSize));  // Put input on stack.
+  sdc1(double_input, MemOperand(sp, 0));
+
+  DoubleToIStub stub(sp, result, 0, true, true);
+  CallStub(&stub);
+
+  Addu(sp, sp, Operand(kDoubleSize));
+  pop(ra);
+
+  bind(&done);
+}
+
+
+void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
+  Label done;
+  DoubleRegister double_scratch = f12;
+  ASSERT(!result.is(object));
+
+  ldc1(double_scratch,
+       MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
+  TryInlineTruncateDoubleToI(result, double_scratch, &done);
+
+ // If we fell through then inline version didn't succeed - call stub instead.
+  push(ra);
+  DoubleToIStub stub(object,
+                     result,
+                     HeapNumber::kValueOffset - kHeapObjectTag,
+                     true,
+                     true);
+  CallStub(&stub);
+  pop(ra);
+
+  bind(&done);
+}
+
+
+void MacroAssembler::TruncateNumberToI(Register object,
+                                       Register result,
+                                       Register heap_number_map,
+                                       Register scratch1,
+                                       Register scratch2,
+                                       Register scratch3,
+                                       Label* not_number) {
+  Label done;
+  Label not_in_int32_range;
+  DoubleRegister double_scratch = f12;
+
+  UntagAndJumpIfSmi(result, object, &done);
+  JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
+  ConvertToInt32(object,
+                 result,
+                 scratch1,
+                 scratch2,
+                 double_scratch,
+                 &not_in_int32_range);
+  jmp(&done);

-  // Load the double value and perform a manual truncation.
-  Register input_high = scratch2;
-  Register input_low = scratch3;
-  Move(input_low, input_high, double_input);
+  bind(&not_in_int32_range);
+  lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
+  lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
   EmitOutOfInt32RangeTruncate(result,
-                              input_high,
-                              input_low,
-                              scratch);
+                              scratch1,
+                              scratch2,
+                              scratch3);
+
   bind(&done);
 }

@@ -4575,40 +4632,6 @@
     bind(&ok);
   }
 }
-
-
-void MacroAssembler::ConvertNumberToInt32(Register object,
-                                          Register dst,
-                                          Register heap_number_map,
-                                          Register scratch1,
-                                          Register scratch2,
-                                          Register scratch3,
-                                          FPURegister double_scratch,
-                                          Label* not_number) {
-  Label done;
-  Label not_in_int32_range;
-
-  UntagAndJumpIfSmi(dst, object, &done);
-  JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
-  ConvertToInt32(object,
-                 dst,
-                 scratch1,
-                 scratch2,
-                 double_scratch,
-                 &not_in_int32_range);
-  jmp(&done);
-
-  bind(&not_in_int32_range);
-  lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
-  lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
-
-  EmitOutOfInt32RangeTruncate(dst,
-                              scratch1,
-                              scratch2,
-                              scratch3);
-
-  bind(&done);
-}


 void MacroAssembler::LoadNumber(Register object,
@@ -5640,6 +5663,30 @@
       Operand(Handle<Map>(isolate()->heap()->allocation_memento_map())));
   bind(&no_memento_available);
 }
+
+
+Register GetRegisterThatIsNotOneOf(Register reg1,
+                                   Register reg2,
+                                   Register reg3,
+                                   Register reg4,
+                                   Register reg5,
+                                   Register reg6) {
+  RegList regs = 0;
+  if (reg1.is_valid()) regs |= reg1.bit();
+  if (reg2.is_valid()) regs |= reg2.bit();
+  if (reg3.is_valid()) regs |= reg3.bit();
+  if (reg4.is_valid()) regs |= reg4.bit();
+  if (reg5.is_valid()) regs |= reg5.bit();
+  if (reg6.is_valid()) regs |= reg6.bit();
+
+  for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
+    Register candidate = Register::FromAllocationIndex(i);
+    if (regs & candidate.bit()) continue;
+    return candidate;
+  }
+  UNREACHABLE();
+  return no_reg;
+}


 bool AreAliased(Register r1, Register r2, Register r3, Register r4) {
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.h Thu Aug 29 03:29:24 2013 UTC +++ /branches/bleeding_edge/src/mips/macro-assembler-mips.h Sun Sep 1 17:22:08 2013 UTC
@@ -90,6 +90,13 @@
 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
 enum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved };

+Register GetRegisterThatIsNotOneOf(Register reg1,
+                                   Register reg2 = no_reg,
+                                   Register reg3 = no_reg,
+                                   Register reg4 = no_reg,
+                                   Register reg5 = no_reg,
+                                   Register reg6 = no_reg);
+
 bool AreAliased(Register r1, Register r2, Register r3, Register r4);


@@ -787,27 +794,37 @@
                                    Register input_low,
                                    Register scratch);

+  // Performs a truncating conversion of a floating point number as used by
+ // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
+  // succeeds, otherwise falls through if result is saturated. On return
+  // 'result' either holds answer, or is clobbered on fall through.
+  //
+  // Only public for the test code in test-code-stubs-arm.cc.
+  void TryInlineTruncateDoubleToI(Register result,
+                                  DoubleRegister input,
+                                  Label* done);
+
   // Performs a truncating conversion of a floating point number as used by
   // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
- // Exits with 'result' holding the answer and all other registers clobbered.
-  void EmitECMATruncate(Register result,
-                        FPURegister double_input,
-                        FPURegister single_scratch,
-                        Register scratch,
-                        Register scratch2,
-                        Register scratch3);
+  // Exits with 'result' holding the answer.
+  void TruncateDoubleToI(Register result, DoubleRegister double_input);
+
+  // Performs a truncating conversion of a heap number as used by
+ // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
+  // must be different registers. Exits with 'result' holding the answer.
+  void TruncateHeapNumberToI(Register result, Register object);

   // Converts the smi or heap number in object to an int32 using the rules
   // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
-  // and brought into the range -2^31 .. +2^31 - 1.
-  void ConvertNumberToInt32(Register object,
-                            Register dst,
-                            Register heap_number_map,
-                            Register scratch1,
-                            Register scratch2,
-                            Register scratch3,
-                            FPURegister double_scratch,
-                            Label* not_int32);
+ // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
+  // different registers.
+  void TruncateNumberToI(Register object,
+                         Register result,
+                         Register heap_number_map,
+                         Register scratch1,
+                         Register scratch2,
+                         Register scratch3,
+                         Label* not_int32);

   // Loads the number from object into dst register.
   // If |object| is neither smi nor heap number, |not_number| is jumped to

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to