Index: test/cctest/compiler/test-typer.cc |
diff --git a/test/cctest/compiler/test-typer.cc b/test/cctest/compiler/test-typer.cc |
index ae65840c702d8b05c51f4c91a140982ec4cbc5b3..2b9d91af02c017e8477af6602151cf2c831078c3 100644 |
--- a/test/cctest/compiler/test-typer.cc |
+++ b/test/cctest/compiler/test-typer.cc |
@@ -4,6 +4,7 @@ |
#include <functional> |
+#include "src/codegen.h" |
#include "src/compiler/node-properties-inl.h" |
#include "src/compiler/typer.h" |
#include "test/cctest/cctest.h" |
@@ -14,7 +15,7 @@ using namespace v8::internal; |
using namespace v8::internal::compiler; |
- |
+// TODO(titzer): generate a large set of deterministic inputs for these tests. |
class TyperTester : public HandleAndZoneScope, public GraphAndBuilders { |
public: |
TyperTester() |
@@ -79,11 +80,15 @@ class TyperTester : public HandleAndZoneScope, public GraphAndBuilders { |
Type* RandomRange(bool int32 = false) { |
std::vector<double>& numbers = int32 ? int32s : integers; |
+ double i = numbers[rng_->NextInt(static_cast<int>(numbers.size()))]; |
+ double j = numbers[rng_->NextInt(static_cast<int>(numbers.size()))]; |
+ return NewRange(i, j); |
+ } |
+ |
+ Type* NewRange(double i, double j) { |
Factory* f = isolate()->factory(); |
- int i = rng_->NextInt(static_cast<int>(numbers.size())); |
- int j = rng_->NextInt(static_cast<int>(numbers.size())); |
- i::Handle<i::Object> min = f->NewNumber(numbers[i]); |
- i::Handle<i::Object> max = f->NewNumber(numbers[j]); |
+ i::Handle<i::Object> min = f->NewNumber(i); |
+ i::Handle<i::Object> max = f->NewNumber(j); |
if (min->Number() > max->Number()) std::swap(min, max); |
return Type::Range(min, max, main_zone()); |
} |
@@ -110,18 +115,47 @@ class TyperTester : public HandleAndZoneScope, public GraphAndBuilders { |
return RandomInt(range->Min()->Number(), range->Max()->Number()); |
} |
+ // Careful, this function runs O(max_width^5) trials. |
+ template <class BinaryFunction> |
+ void TestBinaryArithOpCloseToZero(const Operator* op, BinaryFunction opfun, |
+ int max_width) { |
+ const int min_min = -2 - max_width / 2; |
+ const int max_min = 2 + max_width / 2; |
+ for (int width = 0; width < max_width; width++) { |
+ for (int lmin = min_min; lmin <= max_min; lmin++) { |
+ for (int rmin = min_min; rmin <= max_min; rmin++) { |
+ Type* r1 = NewRange(lmin, lmin + width); |
+ Type* r2 = NewRange(rmin, rmin + width); |
+ Type* expected_type = TypeBinaryOp(op, r1, r2); |
+ |
+ for (int x1 = lmin; x1 < lmin + width; x1++) { |
+ for (int x2 = rmin; x2 < rmin + width; x2++) { |
+ double result_value = opfun(x1, x2); |
+ Type* result_type = Type::Constant( |
+ isolate()->factory()->NewNumber(result_value), main_zone()); |
+ CHECK(result_type->Is(expected_type)); |
+ } |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
template <class BinaryFunction> |
void TestBinaryArithOp(const Operator* op, BinaryFunction opfun) { |
+ TestBinaryArithOpCloseToZero(op, opfun, 8); |
for (int i = 0; i < 100; ++i) { |
Type::RangeType* r1 = RandomRange()->AsRange(); |
Type::RangeType* r2 = RandomRange()->AsRange(); |
Type* expected_type = TypeBinaryOp(op, r1, r2); |
- double x1 = RandomInt(r1); |
- double x2 = RandomInt(r2); |
- double result_value = opfun(x1, x2); |
- Type* result_type = Type::Constant( |
- isolate()->factory()->NewNumber(result_value), main_zone()); |
- CHECK(result_type->Is(expected_type)); |
+ for (int i = 0; i < 10; i++) { |
+ double x1 = RandomInt(r1); |
+ double x2 = RandomInt(r2); |
+ double result_value = opfun(x1, x2); |
+ Type* result_type = Type::Constant( |
+ isolate()->factory()->NewNumber(result_value), main_zone()); |
+ CHECK(result_type->Is(expected_type)); |
+ } |
} |
} |
@@ -131,13 +165,16 @@ class TyperTester : public HandleAndZoneScope, public GraphAndBuilders { |
Type::RangeType* r1 = RandomRange()->AsRange(); |
Type::RangeType* r2 = RandomRange()->AsRange(); |
Type* expected_type = TypeBinaryOp(op, r1, r2); |
- double x1 = RandomInt(r1); |
- double x2 = RandomInt(r2); |
- bool result_value = opfun(x1, x2); |
- Type* result_type = Type::Constant(result_value ? |
- isolate()->factory()->true_value() : |
- isolate()->factory()->false_value(), main_zone()); |
- CHECK(result_type->Is(expected_type)); |
+ for (int i = 0; i < 10; i++) { |
+ double x1 = RandomInt(r1); |
+ double x2 = RandomInt(r2); |
+ bool result_value = opfun(x1, x2); |
+ Type* result_type = |
+ Type::Constant(result_value ? isolate()->factory()->true_value() |
+ : isolate()->factory()->false_value(), |
+ main_zone()); |
+ CHECK(result_type->Is(expected_type)); |
+ } |
} |
} |
@@ -147,12 +184,14 @@ class TyperTester : public HandleAndZoneScope, public GraphAndBuilders { |
Type::RangeType* r1 = RandomRange(true)->AsRange(); |
Type::RangeType* r2 = RandomRange(true)->AsRange(); |
Type* expected_type = TypeBinaryOp(op, r1, r2); |
- int32_t x1 = static_cast<int32_t>(RandomInt(r1)); |
- int32_t x2 = static_cast<int32_t>(RandomInt(r2)); |
- double result_value = opfun(x1, x2); |
- Type* result_type = Type::Constant( |
- isolate()->factory()->NewNumber(result_value), main_zone()); |
- CHECK(result_type->Is(expected_type)); |
+ for (int i = 0; i < 10; i++) { |
+ int32_t x1 = static_cast<int32_t>(RandomInt(r1)); |
+ int32_t x2 = static_cast<int32_t>(RandomInt(r2)); |
+ double result_value = opfun(x1, x2); |
+ Type* result_type = Type::Constant( |
+ isolate()->factory()->NewNumber(result_value), main_zone()); |
+ CHECK(result_type->Is(expected_type)); |
+ } |
} |
} |
@@ -216,6 +255,12 @@ TEST(TypeJSDivide) { |
} |
+TEST(TypeJSModulus) { |
+ TyperTester t; |
+ t.TestBinaryArithOp(t.javascript_.Modulus(), modulo); |
+} |
+ |
+ |
TEST(TypeJSBitwiseOr) { |
TyperTester t; |
t.TestBinaryBitOp(t.javascript_.BitwiseOr(), bit_or); |
@@ -325,10 +370,10 @@ TEST(TypeJSStrictNotEqual) { |
V(Modulus) |
-TEST(Monotonicity) { |
- TyperTester t; |
- #define TEST_OP(name) \ |
- t.TestBinaryMonotonicity(t.javascript_.name()); |
- JSBINOP_LIST(TEST_OP) |
- #undef TEST_OP |
-} |
+#define TEST_FUNC(name) \ |
+ TEST(Monotonicity_##name) { \ |
+ TyperTester t; \ |
+ t.TestBinaryMonotonicity(t.javascript_.name()); \ |
+ } |
+JSBINOP_LIST(TEST_FUNC) |
+#undef TEST_FUNC |