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(®exp_interruption_data.loop_count,
0);
+ v8::base::NoBarrier_Load(®exp_interruption_data.loop_count) <
7;
+ v8::base::NoBarrier_AtomicIncrement(
+ ®exp_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(®exp_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.