Revision: 24469
Author:   [email protected]
Date:     Wed Oct  8 13:44:16 2014 UTC
Log:      Version 3.30.5 (based on bleeding_edge revision r24451)

Performance and stability improvements on all platforms.
https://code.google.com/p/v8/source/detail?r=24469

Modified:
 /trunk/ChangeLog
 /trunk/src/base/functional.h
 /trunk/src/compiler/common-operator.cc
 /trunk/src/version.cc
 /trunk/src/x87/assembler-x87.cc
 /trunk/src/x87/assembler-x87.h
 /trunk/src/x87/full-codegen-x87.cc
 /trunk/src/x87/lithium-x87.cc
 /trunk/src/x87/macro-assembler-x87.cc
 /trunk/src/x87/macro-assembler-x87.h
 /trunk/test/cctest/test-api.cc
 /trunk/test/cctest/test-disasm-x87.cc
 /trunk/test/unittests/base/functional-unittest.cc
 /trunk/test/unittests/compiler/common-operator-unittest.cc

=======================================
--- /trunk/ChangeLog    Wed Oct  8 00:05:11 2014 UTC
+++ /trunk/ChangeLog    Wed Oct  8 13:44:16 2014 UTC
@@ -1,3 +1,8 @@
+2014-10-08: Version 3.30.5
+
+        Performance and stability improvements on all platforms.
+
+
 2014-10-08: Version 3.30.4

         This uses a runtime function to set up the the constructor and its
=======================================
--- /trunk/src/base/functional.h        Wed Oct  8 00:05:11 2014 UTC
+++ /trunk/src/base/functional.h        Wed Oct  8 13:44:16 2014 UTC
@@ -6,6 +6,7 @@
 #define V8_BASE_FUNCTIONAL_H_

 #include <cstddef>
+#include <cstring>
 #include <functional>
 #include <utility>

@@ -67,7 +68,17 @@
 size_t hash_combine(size_t seed, size_t value);
 template <typename T, typename... Ts>
 V8_INLINE size_t hash_combine(T const& v, Ts const&... vs) {
-  return hash_combine(hash<T>()(v), hash_combine(vs...));
+  return hash_combine(hash_combine(vs...), hash<T>()(v));
+}
+
+
+template <typename Iterator>
+V8_INLINE size_t hash_range(Iterator first, Iterator last) {
+  size_t seed = 0;
+  for (; first != last; ++first) {
+    seed = hash_combine(seed, *first);
+  }
+  return seed;
 }


@@ -102,6 +113,16 @@
   // 0 and -0 both hash to zero.
   return v != 0.0 ? hash_value(bit_cast<uint64_t>(v)) : 0;
 }
+
+template <typename T, size_t N>
+V8_INLINE size_t hash_value(const T (&v)[N]) {
+  return hash_range(v, v + N);
+}
+
+template <typename T, size_t N>
+V8_INLINE size_t hash_value(T (&v)[N]) {
+  return hash_range(v, v + N);
+}

 template <typename T>
 V8_INLINE size_t hash_value(T* const& v) {
@@ -148,13 +169,55 @@
   }
 };

-template <typename T1, typename T2>
-struct hash<std::pair<T1, T2> >
-    : public std::unary_function<std::pair<T1, T2>, size_t> {
-  V8_INLINE size_t operator()(std::pair<T1, T2> const& v) const {
-    return ::v8::base::hash_value(v);
-  }
-};
+
+// base::bit_equal_to is a function object class for bitwise equality
+// comparison, similar to std::equal_to, except that the comparison is performed
+// on the bit representation of the operands.
+//
+// base::bit_hash is a function object class for bitwise hashing, similar to +// base::hash. It can be used together with base::bit_equal_to to implement a
+// hash data structure based on the bitwise representation of types.
+
+template <typename T>
+struct bit_equal_to : public std::binary_function<T, T, bool> {};
+
+template <typename T>
+struct bit_hash : public std::unary_function<T, size_t> {};
+
+#define V8_BASE_BIT_SPECIALIZE_TRIVIAL(type)                 \
+  template <>                                                \
+  struct bit_equal_to<type> : public std::equal_to<type> {}; \
+  template <>                                                \
+  struct bit_hash<type> : public hash<type> {};
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(signed char)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned char)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(short)           // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned short)  // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(long)                // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned long)       // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(long long)           // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned long long)  // NOLINT(runtime/int)
+#undef V8_BASE_BIT_SPECIALIZE_TRIVIAL
+
+#define V8_BASE_BIT_SPECIALIZE_BIT_CAST(type, btype) \ + template <> \ + struct bit_equal_to<type> : public std::binary_function<type, type, bool> { \ + V8_INLINE bool operator()(type lhs, type rhs) const { \ + return bit_cast<btype>(lhs) == bit_cast<btype>(rhs); \ + } \ + }; \ + template <> \ + struct bit_hash<type> : public std::unary_function<type, size_t> { \ + V8_INLINE size_t operator()(type v) const { \ + hash<btype> h; \ + return h(bit_cast<btype>(v)); \ + } \
+  };
+V8_BASE_BIT_SPECIALIZE_BIT_CAST(float, uint32_t)
+V8_BASE_BIT_SPECIALIZE_BIT_CAST(double, uint64_t)
+#undef V8_BASE_BIT_SPECIALIZE_BIT_CAST

 }  // namespace base
 }  // namespace v8
=======================================
--- /trunk/src/compiler/common-operator.cc      Wed Oct  8 00:05:11 2014 UTC
+++ /trunk/src/compiler/common-operator.cc      Wed Oct  8 13:44:16 2014 UTC
@@ -150,15 +150,17 @@

const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) {
   return new (zone())
-      Operator1<float>(IrOpcode::kFloat32Constant, Operator::kPure, 0, 1,
-                       "Float32Constant", value);
+      Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>(
+ IrOpcode::kFloat32Constant, Operator::kPure, 0, 1, "Float32Constant",
+          value);
 }


const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
   return new (zone())
-      Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
-                        "Float64Constant", value);
+ Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>( + IrOpcode::kFloat64Constant, Operator::kPure, 0, 1, "Float64Constant",
+          value);
 }


@@ -172,8 +174,9 @@

const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
   return new (zone())
-      Operator1<double>(IrOpcode::kNumberConstant, Operator::kPure, 0, 1,
-                        "NumberConstant", value);
+ Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>( + IrOpcode::kNumberConstant, Operator::kPure, 0, 1, "NumberConstant",
+          value);
 }


=======================================
--- /trunk/src/version.cc       Wed Oct  8 00:05:11 2014 UTC
+++ /trunk/src/version.cc       Wed Oct  8 13:44:16 2014 UTC
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     30
-#define BUILD_NUMBER      4
+#define BUILD_NUMBER      5
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/x87/assembler-x87.cc     Mon Sep 29 00:04:53 2014 UTC
+++ /trunk/src/x87/assembler-x87.cc     Wed Oct  8 13:44:16 2014 UTC
@@ -915,24 +915,24 @@
 }


-void Assembler::ror(Register dst, uint8_t imm8) {
+void Assembler::ror(const Operand& dst, uint8_t imm8) {
   EnsureSpace ensure_space(this);
   DCHECK(is_uint5(imm8));  // illegal shift count
   if (imm8 == 1) {
     EMIT(0xD1);
-    EMIT(0xC8 | dst.code());
+    emit_operand(ecx, dst);
   } else {
     EMIT(0xC1);
-    EMIT(0xC8 | dst.code());
+    emit_operand(ecx, dst);
     EMIT(imm8);
   }
 }


-void Assembler::ror_cl(Register dst) {
+void Assembler::ror_cl(const Operand& dst) {
   EnsureSpace ensure_space(this);
   EMIT(0xD3);
-  EMIT(0xC8 | dst.code());
+  emit_operand(ecx, dst);
 }


=======================================
--- /trunk/src/x87/assembler-x87.h      Mon Sep 29 00:04:53 2014 UTC
+++ /trunk/src/x87/assembler-x87.h      Wed Oct  8 13:44:16 2014 UTC
@@ -725,8 +725,11 @@

   void rcl(Register dst, uint8_t imm8);
   void rcr(Register dst, uint8_t imm8);
-  void ror(Register dst, uint8_t imm8);
-  void ror_cl(Register dst);
+
+  void ror(Register dst, uint8_t imm8) { ror(Operand(dst), imm8); }
+  void ror(const Operand& dst, uint8_t imm8);
+  void ror_cl(Register dst) { ror_cl(Operand(dst)); }
+  void ror_cl(const Operand& dst);

   void sar(Register dst, uint8_t imm8) { sar(Operand(dst), imm8); }
   void sar(const Operand& dst, uint8_t imm8);
=======================================
--- /trunk/src/x87/full-codegen-x87.cc  Wed Oct  1 00:05:35 2014 UTC
+++ /trunk/src/x87/full-codegen-x87.cc  Wed Oct  8 13:44:16 2014 UTC
@@ -2285,6 +2285,14 @@
     CallIC(ic, prop->PropertyFeedbackId());
   }
 }
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
+  // Stack: receiver, home_object, key.
+  SetSourcePosition(prop->position());
+
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+}


 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
@@ -2592,11 +2600,19 @@
     PrepareForBailoutForId(expr->LoadId(), TOS_REG);
     context()->Plug(eax);
   } else {
-    VisitForStackValue(expr->obj());
-    VisitForAccumulatorValue(expr->key());
-    __ pop(LoadDescriptor::ReceiverRegister());                  // Object.
-    __ Move(LoadDescriptor::NameRegister(), result_register());  // Key.
-    EmitKeyedPropertyLoad(expr);
+    if (!expr->IsSuperAccess()) {
+      VisitForStackValue(expr->obj());
+      VisitForAccumulatorValue(expr->key());
+ __ pop(LoadDescriptor::ReceiverRegister()); // Object.
+      __ Move(LoadDescriptor::NameRegister(), result_register());  // Key.
+      EmitKeyedPropertyLoad(expr);
+    } else {
+      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+      EmitLoadHomeObject(expr->obj()->AsSuperReference());
+      __ push(result_register());
+      VisitForStackValue(expr->key());
+      EmitKeyedSuperPropertyLoad(expr);
+    }
     context()->Plug(eax);
   }
 }
@@ -2698,6 +2714,40 @@
   EmitCall(expr, CallICState::METHOD);
 }

+
+void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
+  Expression* callee = expr->expression();
+  DCHECK(callee->IsProperty());
+  Property* prop = callee->AsProperty();
+  DCHECK(prop->IsSuperAccess());
+
+  SetSourcePosition(prop->position());
+  // Load the function from the receiver.
+ SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
+  EmitLoadHomeObject(super_ref);
+  __ push(eax);
+  VisitForAccumulatorValue(super_ref->this_var());
+  __ push(eax);
+  __ push(eax);
+  __ push(Operand(esp, kPointerSize * 2));
+  VisitForStackValue(prop->key());
+  // Stack here:
+  //  - home_object
+  //  - this (receiver)
+  //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
+  //  - home_object
+  //  - key
+  __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+
+  // Replace home_object with target function.
+  __ mov(Operand(esp, kPointerSize), eax);
+
+  // Stack here:
+  // - target function
+  // - this (receiver)
+  EmitCall(expr, CallICState::METHOD);
+}
+

void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
   // Load the arguments.
@@ -2840,9 +2890,12 @@
   } else if (call_type == Call::PROPERTY_CALL) {
     Property* property = callee->AsProperty();
     bool is_named_call = property->key()->IsPropertyName();
-    // super.x() is handled in EmitCallWithLoadIC.
-    if (property->IsSuperAccess() && is_named_call) {
-      EmitSuperCallWithLoadIC(expr);
+    if (property->IsSuperAccess()) {
+      if (is_named_call) {
+        EmitSuperCallWithLoadIC(expr);
+      } else {
+        EmitKeyedSuperCallWithLoadIC(expr);
+      }
     } else {
       {
         PreservePositionScope scope(masm()->positions_recorder());
=======================================
--- /trunk/src/x87/lithium-x87.cc       Wed Oct  8 00:05:11 2014 UTC
+++ /trunk/src/x87/lithium-x87.cc       Wed Oct  8 13:44:16 2014 UTC
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

+#include <sstream>
+
 #include "src/v8.h"

 #if V8_TARGET_ARCH_X87
@@ -378,7 +380,7 @@
   object()->PrintTo(stream);
   std::ostringstream os;
   os << hydrogen()->access() << " <- ";
-  stream->Add(os.c_str());
+  stream->Add(os.str().c_str());
   value()->PrintTo(stream);
 }

=======================================
--- /trunk/src/x87/macro-assembler-x87.cc       Fri Sep 26 00:05:23 2014 UTC
+++ /trunk/src/x87/macro-assembler-x87.cc       Wed Oct  8 13:44:16 2014 UTC
@@ -278,7 +278,7 @@
 }


-void MacroAssembler::LoadUint32NoSSE2(Register src) {
+void MacroAssembler::LoadUint32NoSSE2(const Operand& src) {
   Label done;
   push(src);
   fild_s(Operand(esp, 0));
=======================================
--- /trunk/src/x87/macro-assembler-x87.h        Fri Sep 26 00:05:23 2014 UTC
+++ /trunk/src/x87/macro-assembler-x87.h        Wed Oct  8 13:44:16 2014 UTC
@@ -457,7 +457,10 @@
     j(not_carry, is_smi);
   }

-  void LoadUint32NoSSE2(Register src);
+  void LoadUint32NoSSE2(Register src) {
+    LoadUint32NoSSE2(Operand(src));
+  }
+  void LoadUint32NoSSE2(const Operand& src);

   // Jump the register contains a smi.
   inline void JumpIfSmi(Register value,
=======================================
--- /trunk/test/cctest/test-api.cc      Wed Oct  8 00:05:11 2014 UTC
+++ /trunk/test/cctest/test-api.cc      Wed Oct  8 13:44:16 2014 UTC
@@ -15400,7 +15400,7 @@
 #ifndef V8_INTERPRETED_REGEXP

 struct RegExpInterruptionData {
-  int loop_count;
+  v8::base::Atomic32 loop_count;
   UC16VectorResource* string_resource;
   v8::Persistent<v8::String> string;
 } regexp_interruption_data;
@@ -15412,9 +15412,10 @@
       : Thread(Options("TimeoutThread")), isolate_(isolate) {}

   virtual void Run() {
-    for (regexp_interruption_data.loop_count = 0;
-         regexp_interruption_data.loop_count < 7;
-         regexp_interruption_data.loop_count++) {
+ for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0); + v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
+         v8::base::NoBarrier_AtomicIncrement(
+             &regexp_interruption_data.loop_count, 1)) {
       v8::base::OS::Sleep(50);  // Wait a bit before requesting GC.
       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
     }
@@ -15428,7 +15429,9 @@


 void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
-  if (regexp_interruption_data.loop_count != 2) return;
+ if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
+    return;
+  }
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::String> string = v8::Local<v8::String>::New(
       CcTest::isolate(), regexp_interruption_data.string);
=======================================
--- /trunk/test/cctest/test-disasm-x87.cc       Wed Sep 24 00:05:07 2014 UTC
+++ /trunk/test/cctest/test-disasm-x87.cc       Wed Oct  8 13:44:16 2014 UTC
@@ -201,6 +201,12 @@
   __ rcl(edx, 7);
   __ rcr(edx, 1);
   __ rcr(edx, 7);
+  __ ror(edx, 1);
+  __ ror(edx, 6);
+  __ ror_cl(edx);
+  __ ror(Operand(ebx, ecx, times_4, 10000), 1);
+  __ ror(Operand(ebx, ecx, times_4, 10000), 6);
+  __ ror_cl(Operand(ebx, ecx, times_4, 10000));
   __ sar(edx, 1);
   __ sar(edx, 6);
   __ sar_cl(edx);
=======================================
--- /trunk/test/unittests/base/functional-unittest.cc Wed Oct 8 00:05:11 2014 UTC +++ /trunk/test/unittests/base/functional-unittest.cc Wed Oct 8 13:44:16 2014 UTC
@@ -95,6 +95,39 @@
   }
   EXPECT_LE(vs.size() / 4u, hs.size());
 }
+
+
+TYPED_TEST(FunctionalTest, HashValueArrayUsesHashRange) {
+  TypeParam values[128];
+  this->rng()->NextBytes(&values, sizeof(values));
+ EXPECT_EQ(hash_range(values, values + arraysize(values)), hash_value(values));
+}
+
+
+TYPED_TEST(FunctionalTest, BitEqualTo) {
+  bit_equal_to<TypeParam> pred;
+  for (size_t i = 0; i < 128; ++i) {
+    TypeParam v1, v2;
+    this->rng()->NextBytes(&v1, sizeof(v1));
+    this->rng()->NextBytes(&v2, sizeof(v2));
+    EXPECT_PRED2(pred, v1, v1);
+    EXPECT_PRED2(pred, v2, v2);
+    EXPECT_EQ(memcmp(&v1, &v2, sizeof(TypeParam)) == 0, pred(v1, v2));
+  }
+}
+
+
+TYPED_TEST(FunctionalTest, BitEqualToImpliesSameBitHash) {
+  bit_hash<TypeParam> h;
+  bit_equal_to<TypeParam> e;
+  TypeParam values[32];
+  this->rng()->NextBytes(&values, sizeof(values));
+  TRACED_FOREACH(TypeParam, v1, values) {
+    TRACED_FOREACH(TypeParam, v2, values) {
+      if (e(v1, v2)) EXPECT_EQ(h(v1), h(v2));
+    }
+  }
+}


 namespace {
@@ -124,6 +157,40 @@
     }
   }
 }
+
+
+TEST(FunctionalTest, BitEqualToFloat) {
+  bit_equal_to<float> pred;
+  EXPECT_FALSE(pred(0.0f, -0.0f));
+  EXPECT_FALSE(pred(-0.0f, 0.0f));
+  float const qNaN = std::numeric_limits<float>::quiet_NaN();
+  float const sNaN = std::numeric_limits<float>::signaling_NaN();
+  EXPECT_PRED2(pred, qNaN, qNaN);
+  EXPECT_PRED2(pred, sNaN, sNaN);
+}
+
+
+TEST(FunctionalTest, BitHashFloatDifferentForZeroAndMinusZero) {
+  bit_hash<float> h;
+  EXPECT_NE(h(0.0f), h(-0.0f));
+}
+
+
+TEST(FunctionalTest, BitEqualToDouble) {
+  bit_equal_to<double> pred;
+  EXPECT_FALSE(pred(0.0, -0.0));
+  EXPECT_FALSE(pred(-0.0, 0.0));
+  double const qNaN = std::numeric_limits<double>::quiet_NaN();
+  double const sNaN = std::numeric_limits<double>::signaling_NaN();
+  EXPECT_PRED2(pred, qNaN, qNaN);
+  EXPECT_PRED2(pred, sNaN, sNaN);
+}
+
+
+TEST(FunctionalTest, BitHashDoubleDifferentForZeroAndMinusZero) {
+  bit_hash<double> h;
+  EXPECT_NE(h(0.0), h(-0.0));
+}

 }  // namespace base
 }  // namespace v8
=======================================
--- /trunk/test/unittests/compiler/common-operator-unittest.cc Thu Oct 2 00:05:29 2014 UTC +++ /trunk/test/unittests/compiler/common-operator-unittest.cc Wed Oct 8 13:44:16 2014 UTC
@@ -133,23 +133,93 @@

 const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt};

-const float kFloat32Values[] = {
-    std::numeric_limits<float>::min(), -1.0f, -0.0f, 0.0f, 1.0f,
-    std::numeric_limits<float>::max()};
+
+const float kFloatValues[] = {-std::numeric_limits<float>::infinity(),
+                              std::numeric_limits<float>::min(),
+                              -1.0f,
+                              -0.0f,
+                              0.0f,
+                              1.0f,
+                              std::numeric_limits<float>::max(),
+                              std::numeric_limits<float>::infinity(),
+                              std::numeric_limits<float>::quiet_NaN(),
+                              std::numeric_limits<float>::signaling_NaN()};
+
+
+const double kDoubleValues[] = {-std::numeric_limits<double>::infinity(),
+                                std::numeric_limits<double>::min(),
+                                -1.0,
+                                -0.0,
+                                0.0,
+                                1.0,
+                                std::numeric_limits<double>::max(),
+                                std::numeric_limits<double>::infinity(),
+                                std::numeric_limits<double>::quiet_NaN(),
+ std::numeric_limits<double>::signaling_NaN()};

 }  // namespace


 TEST_F(CommonOperatorTest, Float32Constant) {
-  TRACED_FOREACH(float, value, kFloat32Values) {
+  TRACED_FOREACH(float, value, kFloatValues) {
     const Operator* op = common()->Float32Constant(value);
-    EXPECT_FLOAT_EQ(value, OpParameter<float>(op));
+ EXPECT_PRED2(base::bit_equal_to<float>(), value, OpParameter<float>(op));
     EXPECT_EQ(0, OperatorProperties::GetValueInputCount(op));
     EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
     EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
     EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
     EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
   }
+  TRACED_FOREACH(float, v1, kFloatValues) {
+    TRACED_FOREACH(float, v2, kFloatValues) {
+      const Operator* op1 = common()->Float32Constant(v1);
+      const Operator* op2 = common()->Float32Constant(v2);
+      EXPECT_EQ(bit_cast<uint32_t>(v1) == bit_cast<uint32_t>(v2),
+                op1->Equals(op2));
+    }
+  }
+}
+
+
+TEST_F(CommonOperatorTest, Float64Constant) {
+  TRACED_FOREACH(double, value, kFloatValues) {
+    const Operator* op = common()->Float64Constant(value);
+ EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
+    EXPECT_EQ(0, OperatorProperties::GetValueInputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
+    EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
+  }
+  TRACED_FOREACH(double, v1, kFloatValues) {
+    TRACED_FOREACH(double, v2, kFloatValues) {
+      const Operator* op1 = common()->Float64Constant(v1);
+      const Operator* op2 = common()->Float64Constant(v2);
+      EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
+                op1->Equals(op2));
+    }
+  }
+}
+
+
+TEST_F(CommonOperatorTest, NumberConstant) {
+  TRACED_FOREACH(double, value, kFloatValues) {
+    const Operator* op = common()->NumberConstant(value);
+ EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
+    EXPECT_EQ(0, OperatorProperties::GetValueInputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
+    EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
+  }
+  TRACED_FOREACH(double, v1, kFloatValues) {
+    TRACED_FOREACH(double, v2, kFloatValues) {
+      const Operator* op1 = common()->NumberConstant(v1);
+      const Operator* op2 = common()->NumberConstant(v2);
+      EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
+                op1->Equals(op2));
+    }
+  }
 }


--
--
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/d/optout.

Reply via email to