Reland "Introduce intrinsics for double values in Javascript."
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 7 Mar 2014 14:58:41 +0000 (14:58 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 7 Mar 2014 14:58:41 +0000 (14:58 +0000)
This relands r19704 with a fix to the test case.

R=svenpanne@chromium.org

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

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

22 files changed:
src/a64/lithium-a64.cc
src/a64/lithium-a64.h
src/a64/lithium-codegen-a64.cc
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/d8.gyp
src/full-codegen.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/runtime.cc
src/runtime.h
src/x64/assembler-x64.cc
src/x64/assembler-x64.h
src/x64/disasm-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
src/x64/lithium-x64.h
test/mjsunit/double-intrinsics.js [new file with mode: 0644]

index d2025fcb9a2ffb3d628a05b4f4c9a1a20ea3c0cb..ae32e36537ed81176b4523da510f47fdf94516c0 100644 (file)
@@ -1922,6 +1922,21 @@ LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
+  HValue* value = instr->value();
+  ASSERT(value->representation().IsDouble());
+  return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
+}
+
+
+LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
+  LOperand* lo = UseRegister(instr->lo());
+  LOperand* hi = UseRegister(instr->hi());
+  LOperand* temp = TempRegister();
+  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo, temp));
+}
+
+
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub()
       ? UseFixed(instr->context(), cp)
index 1bfbe85827259691ac9e439bfc1ef79c06e14995..aa1c23ac303932eb21c29cf222dff251192964c8 100644 (file)
@@ -84,6 +84,7 @@ class LCodeGen;
   V(ConstantI)                                  \
   V(ConstantS)                                  \
   V(ConstantT)                                  \
+  V(ConstructDouble)                            \
   V(Context)                                    \
   V(DateField)                                  \
   V(DebugBreak)                                 \
@@ -91,6 +92,7 @@ class LCodeGen;
   V(Deoptimize)                                 \
   V(DivByPowerOf2I)                             \
   V(DivI)                                       \
+  V(DoubleBits)                                 \
   V(DoubleToIntOrSmi)                           \
   V(Drop)                                       \
   V(Dummy)                                      \
@@ -1014,6 +1016,35 @@ class LClampTToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 2> {
 };
 
 
+class LDoubleBits V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LDoubleBits(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
+  DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
+};
+
+
+class LConstructDouble V8_FINAL : public LTemplateInstruction<1, 2, 1> {
+ public:
+  LConstructDouble(LOperand* hi, LOperand* lo, LOperand* temp) {
+    inputs_[0] = hi;
+    inputs_[1] = lo;
+    temps_[0] = temp;
+  }
+
+  LOperand* hi() { return inputs_[0]; }
+  LOperand* lo() { return inputs_[1]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
+};
+
+
 class LClassOfTestAndBranch V8_FINAL : public LControlInstruction<1, 2> {
  public:
   LClassOfTestAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
index e35aa2eb63e97a57a43477f5428b6e60c3ec4538..d3b33147ca71a5978ae9ad8ed623dadc6f0c38a7 100644 (file)
@@ -2224,6 +2224,30 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
 }
 
 
+void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
+  DoubleRegister value_reg = ToDoubleRegister(instr->value());
+  Register result_reg = ToRegister(instr->result());
+  if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
+    __ Fmov(result_reg, value_reg);
+    __ Mov(result_reg, Operand(result_reg, LSR, 32));
+  } else {
+    __ Fmov(result_reg.W(), value_reg.S());
+  }
+}
+
+
+void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
+  Register hi_reg = ToRegister(instr->hi());
+  Register lo_reg = ToRegister(instr->lo());
+  Register temp = ToRegister(instr->temp());
+  DoubleRegister result_reg = ToDoubleRegister(instr->result());
+
+  __ And(temp, lo_reg, Operand(0xffffffff));
+  __ Orr(temp, temp, Operand(hi_reg, LSL, 32));
+  __ Fmov(result_reg, temp);
+}
+
+
 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
   Handle<String> class_name = instr->hydrogen()->class_name();
   Label* true_label = instr->TrueLabel(chunk_);
index c5e6b0486734e3537fdd41f4a9d0eac2c9cabb6c..63109f59adb3515f481ed3c5ff52201db070982e 100644 (file)
@@ -1982,6 +1982,20 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
+  HValue* value = instr->value();
+  ASSERT(value->representation().IsDouble());
+  return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
+}
+
+
+LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
+  LOperand* lo = UseRegister(instr->lo());
+  LOperand* hi = UseRegister(instr->hi());
+  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
+}
+
+
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub()
       ? UseFixed(instr->context(), cp)
index 6217f5419f8c40b653dcf39e1005cf7644636af2..a304258dcc55c4513054b592a7b8b8457291617f 100644 (file)
@@ -80,6 +80,7 @@ class LCodeGen;
   V(ConstantI)                                  \
   V(ConstantS)                                  \
   V(ConstantT)                                  \
+  V(ConstructDouble)                            \
   V(Context)                                    \
   V(DateField)                                  \
   V(DebugBreak)                                 \
@@ -87,6 +88,7 @@ class LCodeGen;
   V(Deoptimize)                                 \
   V(DivByPowerOf2I)                             \
   V(DivI)                                       \
+  V(DoubleBits)                                 \
   V(DoubleToI)                                  \
   V(DoubleToSmi)                                \
   V(Drop)                                       \
@@ -2439,6 +2441,33 @@ class LClampTToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 1> {
 };
 
 
+class LDoubleBits V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LDoubleBits(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
+  DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
+};
+
+
+class LConstructDouble V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+ public:
+  LConstructDouble(LOperand* hi, LOperand* lo) {
+    inputs_[0] = hi;
+    inputs_[1] = lo;
+  }
+
+  LOperand* hi() { return inputs_[0]; }
+  LOperand* lo() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
+};
+
+
 class LAllocate V8_FINAL : public LTemplateInstruction<1, 2, 2> {
  public:
   LAllocate(LOperand* context,
index 6b38fd13ba8846739e243561393d7af13dfbcdc6..a95bb5e859ddcca7cb3dcafb8bd4082b4a7971cc 100644 (file)
@@ -5276,6 +5276,26 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
 }
 
 
+void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
+  DwVfpRegister value_reg = ToDoubleRegister(instr->value());
+  Register result_reg = ToRegister(instr->result());
+  if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
+    __ VmovHigh(result_reg, value_reg);
+  } else {
+    __ VmovLow(result_reg, value_reg);
+  }
+}
+
+
+void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
+  Register hi_reg = ToRegister(instr->hi());
+  Register lo_reg = ToRegister(instr->lo());
+  DwVfpRegister result_reg = ToDoubleRegister(instr->result());
+  __ VmovHigh(result_reg, hi_reg);
+  __ VmovLow(result_reg, lo_reg);
+}
+
+
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate V8_FINAL : public LDeferredCode {
    public:
index 0e51baaacac06825ba682ccfbb3b8407af0fff47..98ec04fc86452ff637a567ac50b3f69864751793 100644 (file)
@@ -31,7 +31,7 @@
     'console%': '',
     # Enable support for Intel VTune. Supported on ia32/x64 only
     'v8_enable_vtunejit%': 0,
-    'v8_enable_i18n_support%': 1,
+    'v8_enable_i18n_support%': 0,
     'v8_toolset_for_d8%': 'target',
   },
   'includes': ['../build/toolchain.gypi', '../build/features.gypi'],
index 96410747a266647b0df14b226a0b9ad8f7fcce24..d116bae581a80fa3636f9ae1c7e41c48bb03d789 100644 (file)
@@ -939,6 +939,34 @@ void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitDoubleHi(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForStackValue(args->at(0));
+  masm()->CallRuntime(Runtime::kDoubleHi, 1);
+  context()->Plug(result_register());
+}
+
+
+void FullCodeGenerator::EmitDoubleLo(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForStackValue(args->at(0));
+  masm()->CallRuntime(Runtime::kDoubleLo, 1);
+  context()->Plug(result_register());
+}
+
+
+void FullCodeGenerator::EmitConstructDouble(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 2);
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+  masm()->CallRuntime(Runtime::kConstructDouble, 2);
+  context()->Plug(result_register());
+}
+
+
 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
   switch (expr->op()) {
     case Token::COMMA:
index da586d2b4681be28e3bc0b0304dddc18855a6f7d..4c54c1a33492a800bdecc49a6128de8572682932 100644 (file)
@@ -102,12 +102,14 @@ class LChunkBuilder;
   V(CompareObjectEqAndBranch)                  \
   V(CompareMap)                                \
   V(Constant)                                  \
+  V(ConstructDouble)                           \
   V(Context)                                   \
   V(DateField)                                 \
   V(DebugBreak)                                \
   V(DeclareGlobals)                            \
   V(Deoptimize)                                \
   V(Div)                                       \
+  V(DoubleBits)                                \
   V(DummyUse)                                  \
   V(EnterInlined)                              \
   V(EnvironmentMarker)                         \
@@ -1820,6 +1822,65 @@ class HClampToUint8 V8_FINAL : public HUnaryOperation {
 };
 
 
+class HDoubleBits V8_FINAL : public HUnaryOperation {
+ public:
+  enum Bits { HIGH, LOW };
+  DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
+
+  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+    return Representation::Double();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
+
+  Bits bits() { return bits_; }
+
+ protected:
+  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
+    return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
+  }
+
+ private:
+  HDoubleBits(HValue* value, Bits bits)
+      : HUnaryOperation(value), bits_(bits) {
+    set_representation(Representation::Integer32());
+    SetFlag(kUseGVN);
+  }
+
+  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+
+  Bits bits_;
+};
+
+
+class HConstructDouble V8_FINAL : public HTemplateInstruction<2> {
+ public:
+  DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
+
+  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+    return Representation::Integer32();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
+
+  HValue* hi() { return OperandAt(0); }
+  HValue* lo() { return OperandAt(1); }
+
+ protected:
+  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
+
+ private:
+  explicit HConstructDouble(HValue* hi, HValue* lo) {
+    set_representation(Representation::Double());
+    SetFlag(kUseGVN);
+    SetOperandAt(0, hi);
+    SetOperandAt(1, lo);
+  }
+
+  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+};
+
+
 enum RemovableSimulate {
   REMOVABLE_SIMULATE,
   FIXED_SIMULATE
index 5324ef39cb320f0662ffbefec360cf87a4bf93f8..25fc74973a8a721c0c3afdffbd76722d6026c5bc 100644 (file)
@@ -10509,6 +10509,35 @@ void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
 }
 
 
+void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
+  ASSERT_EQ(1, call->arguments()->length());
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+  HValue* value = Pop();
+  HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
+  return ast_context()->ReturnInstruction(result, call->id());
+}
+
+
+void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
+  ASSERT_EQ(1, call->arguments()->length());
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+  HValue* value = Pop();
+  HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
+  return ast_context()->ReturnInstruction(result, call->id());
+}
+
+
+void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
+  ASSERT_EQ(2, call->arguments()->length());
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
+  HValue* lo = Pop();
+  HValue* hi = Pop();
+  HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
+  return ast_context()->ReturnInstruction(result, call->id());
+}
+
+
 // Construct a RegExp exec result with two in-object properties.
 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
   ASSERT_EQ(3, call->arguments()->length());
index 827add3738e591f612f3e08c8cb7a3eab2af1d40..cbad03060f256dd540ced0a9217fb6a3b0521a9c 100644 (file)
@@ -5766,6 +5766,45 @@ void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
 }
 
 
+void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
+  CpuFeatureScope scope(masm(), SSE2);
+  XMMRegister value_reg = ToDoubleRegister(instr->value());
+  Register result_reg = ToRegister(instr->result());
+  if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
+    if (CpuFeatures::IsSupported(SSE4_1)) {
+      CpuFeatureScope scope2(masm(), SSE4_1);
+      __ pextrd(result_reg, value_reg, 1);
+    } else {
+      XMMRegister xmm_scratch = double_scratch0();
+      __ pshufd(xmm_scratch, value_reg, 1);
+      __ movd(result_reg, xmm_scratch);
+    }
+  } else {
+    __ movd(result_reg, value_reg);
+  }
+}
+
+
+void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
+  Register hi_reg = ToRegister(instr->hi());
+  Register lo_reg = ToRegister(instr->lo());
+  XMMRegister result_reg = ToDoubleRegister(instr->result());
+  CpuFeatureScope scope(masm(), SSE2);
+
+  if (CpuFeatures::IsSupported(SSE4_1)) {
+    CpuFeatureScope scope2(masm(), SSE4_1);
+    __ movd(result_reg, lo_reg);
+    __ pinsrd(result_reg, hi_reg, 1);
+  } else {
+    XMMRegister xmm_scratch = double_scratch0();
+    __ movd(result_reg, hi_reg);
+    __ psllq(result_reg, 32);
+    __ movd(xmm_scratch, lo_reg);
+    __ orps(result_reg, xmm_scratch);
+  }
+}
+
+
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate V8_FINAL : public LDeferredCode {
    public:
index 4ff765b87bb83cca9cd703fe3f6d60731c2c2621..b513f85c0b55802b1a278d6a9381fbf5544bda4f 100644 (file)
@@ -1990,6 +1990,20 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
+  HValue* value = instr->value();
+  ASSERT(value->representation().IsDouble());
+  return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
+}
+
+
+LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
+  LOperand* lo = UseRegister(instr->lo());
+  LOperand* hi = UseRegister(instr->hi());
+  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
+}
+
+
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), esi) : NULL;
   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
index 07c941ae087ddd05411b15234bff747f5f3bc81c..03144b2a5409100d8b722a6f47b0e70694b6b3fb 100644 (file)
@@ -82,6 +82,7 @@ class LCodeGen;
   V(ConstantI)                                  \
   V(ConstantS)                                  \
   V(ConstantT)                                  \
+  V(ConstructDouble)                            \
   V(Context)                                    \
   V(DateField)                                  \
   V(DebugBreak)                                 \
@@ -89,6 +90,7 @@ class LCodeGen;
   V(Deoptimize)                                 \
   V(DivByPowerOf2I)                             \
   V(DivI)                                       \
+  V(DoubleBits)                                 \
   V(DoubleToI)                                  \
   V(DoubleToSmi)                                \
   V(Drop)                                       \
@@ -2468,6 +2470,33 @@ class LCheckNonSmi V8_FINAL : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LDoubleBits V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LDoubleBits(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
+  DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
+};
+
+
+class LConstructDouble V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+ public:
+  LConstructDouble(LOperand* hi, LOperand* lo) {
+    inputs_[0] = hi;
+    inputs_[1] = lo;
+  }
+
+  LOperand* hi() { return inputs_[0]; }
+  LOperand* lo() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
+};
+
+
 class LAllocate V8_FINAL : public LTemplateInstruction<1, 2, 1> {
  public:
   LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
index 5fe69c26b3e0a44af6761a6ff3f5c60ae86b00eb..c0c87a457d3ad870d701f6747d23a13e644fd741 100644 (file)
@@ -7665,6 +7665,35 @@ RUNTIME_UNARY_MATH(log)
 #undef RUNTIME_UNARY_MATH
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_DoubleHi) {
+  SealHandleScope shs(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
+  uint64_t integer = double_to_uint64(x);
+  integer = (integer >> 32) & 0xFFFFFFFFu;
+  return isolate->heap()->NumberFromDouble(static_cast<int32_t>(integer));
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_DoubleLo) {
+  SealHandleScope shs(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
+  return isolate->heap()->NumberFromDouble(
+      static_cast<int32_t>(double_to_uint64(x) & 0xFFFFFFFFu));
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ConstructDouble) {
+  SealHandleScope shs(isolate);
+  ASSERT(args.length() == 2);
+  CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
+  CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
+  uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
+  return isolate->heap()->AllocateHeapNumber(uint64_to_double(result));
+}
+
+
 // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm
 // Using initial approximation adapted from Kahan's cbrt and 4 iterations
 // of Newton's method.
index ff874afafb1ac42b831497e22996539ddfaa2008..480edaf239861329f4fce9844c72ab38da76afaf 100644 (file)
@@ -656,7 +656,10 @@ namespace internal {
   F(RegExpExec, 4, 1)                                                        \
   F(RegExpConstructResult, 3, 1)                                             \
   F(GetFromCache, 2, 1)                                                      \
-  F(NumberToString, 1, 1)
+  F(NumberToString, 1, 1)                                                    \
+  F(DoubleHi, 1, 1)                                                          \
+  F(DoubleLo, 1, 1)                                                          \
+  F(ConstructDouble, 2, 1)
 
 
 //---------------------------------------------------------------------------
index e7784259707cb1a046a8bf221d0ecc404bc131e5..63f0533cd11395f14049e328174bd3c89e8c0b25 100644 (file)
@@ -2798,6 +2798,16 @@ void Assembler::movss(const Operand& src, XMMRegister dst) {
 }
 
 
+void Assembler::psllq(XMMRegister reg, byte imm8) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit(0x0F);
+  emit(0x73);
+  emit_sse_operand(rsi, reg);  // rsi == 6
+  emit(imm8);
+}
+
+
 void Assembler::cvttss2si(Register dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   emit(0xF3);
index d81cb741011ba939b9ba5e08d68ada2cbb3bca25..b1b50c047b8a45ed153aa067ea0212a1325f8ca5 100644 (file)
@@ -1381,6 +1381,8 @@ class Assembler : public AssemblerBase {
 
   void movapd(XMMRegister dst, XMMRegister src);
 
+  void psllq(XMMRegister reg, byte imm8);
+
   void cvttsd2si(Register dst, const Operand& src);
   void cvttsd2si(Register dst, XMMRegister src);
   void cvttsd2siq(Register dst, XMMRegister src);
index f0f399ec0a73f0a0142f1f4c87e6d19a201bb853..b870eae8544a2466fcb4b7a2c21665a2bb192495 100644 (file)
@@ -1089,6 +1089,11 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
       } else if (opcode == 0x50) {
         AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
         current += PrintRightXMMOperand(current);
+      } else if (opcode == 0x73) {
+        current += 1;
+        ASSERT(regop == 6);
+        AppendToBuffer("psllq,%s,%d", NameOfXMMRegister(rm), *current & 0x7f);
+        current += 1;
       } else {
         const char* mnemonic = "?";
         if (opcode == 0x54) {
index 5e84347e1283ce46d634d8fdaddb79867c46fe8e..4dc9d4a34a9f49c6bf7c41679f522a2e188cdd45 100644 (file)
@@ -5069,6 +5069,30 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
 }
 
 
+void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
+  XMMRegister value_reg = ToDoubleRegister(instr->value());
+  Register result_reg = ToRegister(instr->result());
+  if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
+    __ movq(result_reg, value_reg);
+    __ shr(result_reg, Immediate(32));
+  } else {
+    __ movd(result_reg, value_reg);
+  }
+}
+
+
+void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
+  Register hi_reg = ToRegister(instr->hi());
+  Register lo_reg = ToRegister(instr->lo());
+  XMMRegister result_reg = ToDoubleRegister(instr->result());
+  XMMRegister xmm_scratch = double_scratch0();
+  __ movd(result_reg, hi_reg);
+  __ psllq(result_reg, 32);
+  __ movd(xmm_scratch, lo_reg);
+  __ orps(result_reg, xmm_scratch);
+}
+
+
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate V8_FINAL : public LDeferredCode {
    public:
index d0123456738e9452a32077641654274595dfa11b..27001abb7d866087d4a17222531ca32b71f148b9 100644 (file)
@@ -1870,6 +1870,20 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
+  HValue* value = instr->value();
+  ASSERT(value->representation().IsDouble());
+  return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
+}
+
+
+LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
+  LOperand* lo = UseRegister(instr->lo());
+  LOperand* hi = UseRegister(instr->hi());
+  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
+}
+
+
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), rsi) : NULL;
   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
index 29cfc5fccc256f4df97386f17f05218ab8be03d0..c6a6850b967b8275ed508dd29b3ea2bb4510d06d 100644 (file)
@@ -80,6 +80,7 @@ class LCodeGen;
   V(ConstantI)                                  \
   V(ConstantS)                                  \
   V(ConstantT)                                  \
+  V(ConstructDouble)                            \
   V(Context)                                    \
   V(DateField)                                  \
   V(DebugBreak)                                 \
@@ -87,6 +88,7 @@ class LCodeGen;
   V(Deoptimize)                                 \
   V(DivByPowerOf2I)                             \
   V(DivI)                                       \
+  V(DoubleBits)                                 \
   V(DoubleToI)                                  \
   V(DoubleToSmi)                                \
   V(Drop)                                       \
@@ -2372,6 +2374,33 @@ class LCheckNonSmi V8_FINAL : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LDoubleBits V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LDoubleBits(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
+  DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
+};
+
+
+class LConstructDouble V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+ public:
+  LConstructDouble(LOperand* hi, LOperand* lo) {
+    inputs_[0] = hi;
+    inputs_[1] = lo;
+  }
+
+  LOperand* hi() { return inputs_[0]; }
+  LOperand* lo() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
+};
+
+
 class LAllocate V8_FINAL : public LTemplateInstruction<1, 2, 1> {
  public:
   LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
diff --git a/test/mjsunit/double-intrinsics.js b/test/mjsunit/double-intrinsics.js
new file mode 100644 (file)
index 0000000..16d6538
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function assertDoubleBits(hi, lo, x) {
+  hi = hi | 0;
+  lo = lo | 0;
+  assertEquals(x, %_ConstructDouble(hi, lo));
+  assertEquals(hi, %_DoubleHi(x));
+  assertEquals(lo, %_DoubleLo(x));
+  assertEquals(x, %_ConstructDouble(%_DoubleHi(x), %_DoubleLo(x)));
+}
+
+
+var tests = [0x7ff00000, 0x00000000, Infinity,
+             0xfff00000, 0x00000000, -Infinity,
+             0x80000000, 0x00000000, -0,
+             0x400921fb, 0x54442d18, Math.PI,
+             0xc00921fb, 0x54442d18, -Math.PI,
+             0x4005bf0a, 0x8b145769, Math.E,
+             0xc005bf0a, 0x8b145769, -Math.E,
+             0xbfe80000, 0x00000000, -0.75];
+
+
+for (var i = 0; i < tests.length; i += 3) {
+  assertDoubleBits(tests[i], tests[i + 1], tests[i + 2]);
+}
+
+%OptimizeFunctionOnNextCall(assertDoubleBits);
+
+for (var i = 0; i < tests.length; i += 3) {
+  assertDoubleBits(tests[i], tests[i + 1], tests[i + 2]);
+  assertOptimized(assertDoubleBits);
+}