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