| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "test/unittests/compiler/graph-unittest.h" | 5 #include "test/unittests/compiler/graph-unittest.h" |
| 6 | 6 |
| 7 #include "src/compiler/js-builtin-reducer.h" | 7 #include "src/compiler/js-builtin-reducer.h" |
| 8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 10 #include "src/compiler/typer.h" | 10 #include "src/compiler/typer.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 JSBuiltinReducer reducer(&jsgraph); | 28 JSBuiltinReducer reducer(&jsgraph); |
| 29 return reducer.Reduce(node); | 29 return reducer.Reduce(node); |
| 30 } | 30 } |
| 31 | 31 |
| 32 Node* Parameter(Type* t, int32_t index = 0) { | 32 Node* Parameter(Type* t, int32_t index = 0) { |
| 33 Node* n = graph()->NewNode(common()->Parameter(index), graph()->start()); | 33 Node* n = graph()->NewNode(common()->Parameter(index), graph()->start()); |
| 34 NodeProperties::SetBounds(n, Bounds(Type::None(), t)); | 34 NodeProperties::SetBounds(n, Bounds(Type::None(), t)); |
| 35 return n; | 35 return n; |
| 36 } | 36 } |
| 37 | 37 |
| 38 Handle<JSFunction> MathFunction(const char* name) { |
| 39 Handle<Object> m = |
| 40 JSObject::GetProperty(isolate()->global_object(), |
| 41 isolate()->factory()->NewStringFromAsciiChecked( |
| 42 "Math")).ToHandleChecked(); |
| 43 Handle<JSFunction> f = Handle<JSFunction>::cast( |
| 44 JSObject::GetProperty( |
| 45 m, isolate()->factory()->NewStringFromAsciiChecked(name)) |
| 46 .ToHandleChecked()); |
| 47 return f; |
| 48 } |
| 49 |
| 38 JSOperatorBuilder* javascript() { return &javascript_; } | 50 JSOperatorBuilder* javascript() { return &javascript_; } |
| 39 | 51 |
| 40 private: | 52 private: |
| 41 JSOperatorBuilder javascript_; | 53 JSOperatorBuilder javascript_; |
| 42 }; | 54 }; |
| 43 | 55 |
| 44 | 56 |
| 45 namespace { | 57 namespace { |
| 46 | 58 |
| 47 // TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering. | 59 // TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering. |
| 48 Type* const kNumberTypes[] = { | 60 Type* const kNumberTypes[] = { |
| 49 Type::UnsignedSmall(), Type::OtherSignedSmall(), Type::OtherUnsigned31(), | 61 Type::UnsignedSmall(), Type::OtherSignedSmall(), Type::OtherUnsigned31(), |
| 50 Type::OtherUnsigned32(), Type::OtherSigned32(), Type::SignedSmall(), | 62 Type::OtherUnsigned32(), Type::OtherSigned32(), Type::SignedSmall(), |
| 51 Type::Signed32(), Type::Unsigned32(), Type::Integral32(), | 63 Type::Signed32(), Type::Unsigned32(), Type::Integral32(), |
| 52 Type::MinusZero(), Type::NaN(), Type::OtherNumber(), | 64 Type::MinusZero(), Type::NaN(), Type::OtherNumber(), |
| 53 Type::OrderedNumber(), Type::Number()}; | 65 Type::OrderedNumber(), Type::Number()}; |
| 54 | 66 |
| 55 } // namespace | 67 } // namespace |
| 56 | 68 |
| 57 | 69 |
| 58 // ----------------------------------------------------------------------------- | 70 // ----------------------------------------------------------------------------- |
| 59 // Math.abs | 71 // Math.abs |
| 60 | 72 |
| 61 | 73 |
| 62 TEST_F(JSBuiltinReducerTest, MathAbs) { | 74 TEST_F(JSBuiltinReducerTest, MathAbs) { |
| 63 Handle<JSFunction> f(isolate()->context()->math_abs_fun()); | 75 Handle<JSFunction> f = MathFunction("abs"); |
| 64 | 76 |
| 65 TRACED_FOREACH(Type*, t0, kNumberTypes) { | 77 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 66 Node* p0 = Parameter(t0, 0); | 78 Node* p0 = Parameter(t0, 0); |
| 67 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | 79 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); |
| 68 Node* call = | 80 Node* call = |
| 69 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), | 81 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), |
| 70 fun, UndefinedConstant(), p0); | 82 fun, UndefinedConstant(), p0); |
| 71 Reduction r = Reduce(call); | 83 Reduction r = Reduce(call); |
| 72 | 84 |
| 73 if (t0->Is(Type::Unsigned32())) { | 85 if (t0->Is(Type::Unsigned32())) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 87 } | 99 } |
| 88 } | 100 } |
| 89 } | 101 } |
| 90 | 102 |
| 91 | 103 |
| 92 // ----------------------------------------------------------------------------- | 104 // ----------------------------------------------------------------------------- |
| 93 // Math.sqrt | 105 // Math.sqrt |
| 94 | 106 |
| 95 | 107 |
| 96 TEST_F(JSBuiltinReducerTest, MathSqrt) { | 108 TEST_F(JSBuiltinReducerTest, MathSqrt) { |
| 97 Handle<JSFunction> f(isolate()->context()->math_sqrt_fun()); | 109 Handle<JSFunction> f = MathFunction("sqrt"); |
| 98 | 110 |
| 99 TRACED_FOREACH(Type*, t0, kNumberTypes) { | 111 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 100 Node* p0 = Parameter(t0, 0); | 112 Node* p0 = Parameter(t0, 0); |
| 101 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | 113 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); |
| 102 Node* call = | 114 Node* call = |
| 103 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), | 115 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), |
| 104 fun, UndefinedConstant(), p0); | 116 fun, UndefinedConstant(), p0); |
| 105 Reduction r = Reduce(call); | 117 Reduction r = Reduce(call); |
| 106 | 118 |
| 107 ASSERT_TRUE(r.Changed()); | 119 ASSERT_TRUE(r.Changed()); |
| 108 EXPECT_THAT(r.replacement(), IsFloat64Sqrt(p0)); | 120 EXPECT_THAT(r.replacement(), IsFloat64Sqrt(p0)); |
| 109 } | 121 } |
| 110 } | 122 } |
| 111 | 123 |
| 112 | 124 |
| 113 // ----------------------------------------------------------------------------- | 125 // ----------------------------------------------------------------------------- |
| 114 // Math.max | 126 // Math.max |
| 115 | 127 |
| 116 | 128 |
| 117 TEST_F(JSBuiltinReducerTest, MathMax0) { | 129 TEST_F(JSBuiltinReducerTest, MathMax0) { |
| 118 Handle<JSFunction> f(isolate()->context()->math_max_fun()); | 130 Handle<JSFunction> f = MathFunction("max"); |
| 119 | 131 |
| 120 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | 132 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); |
| 121 Node* call = | 133 Node* call = |
| 122 graph()->NewNode(javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS), | 134 graph()->NewNode(javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS), |
| 123 fun, UndefinedConstant()); | 135 fun, UndefinedConstant()); |
| 124 Reduction r = Reduce(call); | 136 Reduction r = Reduce(call); |
| 125 | 137 |
| 126 ASSERT_TRUE(r.Changed()); | 138 ASSERT_TRUE(r.Changed()); |
| 127 EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY)); | 139 EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY)); |
| 128 } | 140 } |
| 129 | 141 |
| 130 | 142 |
| 131 TEST_F(JSBuiltinReducerTest, MathMax1) { | 143 TEST_F(JSBuiltinReducerTest, MathMax1) { |
| 132 Handle<JSFunction> f(isolate()->context()->math_max_fun()); | 144 Handle<JSFunction> f = MathFunction("max"); |
| 133 | 145 |
| 134 TRACED_FOREACH(Type*, t0, kNumberTypes) { | 146 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 135 Node* p0 = Parameter(t0, 0); | 147 Node* p0 = Parameter(t0, 0); |
| 136 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | 148 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); |
| 137 Node* call = | 149 Node* call = |
| 138 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), | 150 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), |
| 139 fun, UndefinedConstant(), p0); | 151 fun, UndefinedConstant(), p0); |
| 140 Reduction r = Reduce(call); | 152 Reduction r = Reduce(call); |
| 141 | 153 |
| 142 ASSERT_TRUE(r.Changed()); | 154 ASSERT_TRUE(r.Changed()); |
| 143 EXPECT_THAT(r.replacement(), p0); | 155 EXPECT_THAT(r.replacement(), p0); |
| 144 } | 156 } |
| 145 } | 157 } |
| 146 | 158 |
| 147 | 159 |
| 148 TEST_F(JSBuiltinReducerTest, MathMax2) { | 160 TEST_F(JSBuiltinReducerTest, MathMax2) { |
| 149 Handle<JSFunction> f(isolate()->context()->math_max_fun()); | 161 Handle<JSFunction> f = MathFunction("max"); |
| 150 | 162 |
| 151 TRACED_FOREACH(Type*, t0, kNumberTypes) { | 163 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 152 TRACED_FOREACH(Type*, t1, kNumberTypes) { | 164 TRACED_FOREACH(Type*, t1, kNumberTypes) { |
| 153 Node* p0 = Parameter(t0, 0); | 165 Node* p0 = Parameter(t0, 0); |
| 154 Node* p1 = Parameter(t1, 1); | 166 Node* p1 = Parameter(t1, 1); |
| 155 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | 167 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); |
| 156 Node* call = graph()->NewNode( | 168 Node* call = graph()->NewNode( |
| 157 javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun, | 169 javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun, |
| 158 UndefinedConstant(), p0, p1); | 170 UndefinedConstant(), p0, p1); |
| 159 Reduction r = Reduce(call); | 171 Reduction r = Reduce(call); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 175 } | 187 } |
| 176 } | 188 } |
| 177 } | 189 } |
| 178 | 190 |
| 179 | 191 |
| 180 // ----------------------------------------------------------------------------- | 192 // ----------------------------------------------------------------------------- |
| 181 // Math.imul | 193 // Math.imul |
| 182 | 194 |
| 183 | 195 |
| 184 TEST_F(JSBuiltinReducerTest, MathImul) { | 196 TEST_F(JSBuiltinReducerTest, MathImul) { |
| 185 Handle<JSFunction> f(isolate()->context()->math_imul_fun()); | 197 Handle<JSFunction> f = MathFunction("imul"); |
| 186 | 198 |
| 187 TRACED_FOREACH(Type*, t0, kNumberTypes) { | 199 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 188 TRACED_FOREACH(Type*, t1, kNumberTypes) { | 200 TRACED_FOREACH(Type*, t1, kNumberTypes) { |
| 189 Node* p0 = Parameter(t0, 0); | 201 Node* p0 = Parameter(t0, 0); |
| 190 Node* p1 = Parameter(t1, 1); | 202 Node* p1 = Parameter(t1, 1); |
| 191 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | 203 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); |
| 192 Node* call = graph()->NewNode( | 204 Node* call = graph()->NewNode( |
| 193 javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun, | 205 javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun, |
| 194 UndefinedConstant(), p0, p1); | 206 UndefinedConstant(), p0, p1); |
| 195 Reduction r = Reduce(call); | 207 Reduction r = Reduce(call); |
| 196 | 208 |
| 197 if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) { | 209 if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) { |
| 198 ASSERT_TRUE(r.Changed()); | 210 ASSERT_TRUE(r.Changed()); |
| 199 EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1)); | 211 EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1)); |
| 200 } else { | 212 } else { |
| 201 ASSERT_FALSE(r.Changed()); | 213 ASSERT_FALSE(r.Changed()); |
| 202 EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode()); | 214 EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode()); |
| 203 } | 215 } |
| 204 } | 216 } |
| 205 } | 217 } |
| 206 } | 218 } |
| 207 | 219 |
| 208 | 220 |
| 209 // ----------------------------------------------------------------------------- | 221 // ----------------------------------------------------------------------------- |
| 210 // Math.fround | 222 // Math.fround |
| 211 | 223 |
| 212 | 224 |
| 213 TEST_F(JSBuiltinReducerTest, MathFround) { | 225 TEST_F(JSBuiltinReducerTest, MathFround) { |
| 214 Handle<Object> m = | 226 Handle<JSFunction> f = MathFunction("fround"); |
| 215 JSObject::GetProperty(isolate()->global_object(), | |
| 216 isolate()->factory()->NewStringFromAsciiChecked( | |
| 217 "Math")).ToHandleChecked(); | |
| 218 Handle<JSFunction> f = Handle<JSFunction>::cast( | |
| 219 JSObject::GetProperty(m, isolate()->factory()->NewStringFromAsciiChecked( | |
| 220 "fround")).ToHandleChecked()); | |
| 221 | 227 |
| 222 TRACED_FOREACH(Type*, t0, kNumberTypes) { | 228 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 223 Node* p0 = Parameter(t0, 0); | 229 Node* p0 = Parameter(t0, 0); |
| 224 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); | 230 Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); |
| 225 Node* call = | 231 Node* call = |
| 226 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), | 232 graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), |
| 227 fun, UndefinedConstant(), p0); | 233 fun, UndefinedConstant(), p0); |
| 228 Reduction r = Reduce(call); | 234 Reduction r = Reduce(call); |
| 229 | 235 |
| 230 ASSERT_TRUE(r.Changed()); | 236 ASSERT_TRUE(r.Changed()); |
| 231 EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0)); | 237 EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0)); |
| 232 } | 238 } |
| 233 } | 239 } |
| 234 | 240 |
| 235 } // namespace compiler | 241 } // namespace compiler |
| 236 } // namespace internal | 242 } // namespace internal |
| 237 } // namespace v8 | 243 } // namespace v8 |
| OLD | NEW |