deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / unittests / compiler / js-intrinsic-lowering-unittest.cc
1 // Copyright 2015 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/access-builder.h"
6 #include "src/compiler/js-graph.h"
7 #include "src/compiler/js-intrinsic-lowering.h"
8 #include "src/compiler/js-operator.h"
9 #include "test/unittests/compiler/graph-unittest.h"
10 #include "test/unittests/compiler/node-test-utils.h"
11 #include "testing/gmock-support.h"
12
13 using testing::_;
14 using testing::AllOf;
15 using testing::BitEq;
16 using testing::Capture;
17 using testing::CaptureEq;
18
19
20 namespace v8 {
21 namespace internal {
22 namespace compiler {
23
24 class JSIntrinsicLoweringTest : public GraphTest {
25  public:
26   JSIntrinsicLoweringTest() : GraphTest(3), javascript_(zone()) {}
27   ~JSIntrinsicLoweringTest() OVERRIDE {}
28
29  protected:
30   Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
31                                    MachineOperatorBuilder::kNoFlags) {
32     MachineOperatorBuilder machine(zone(), kMachPtr, flags);
33     JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
34     JSIntrinsicLowering reducer(&jsgraph);
35     return reducer.Reduce(node);
36   }
37
38   JSOperatorBuilder* javascript() { return &javascript_; }
39
40  private:
41   JSOperatorBuilder javascript_;
42 };
43
44
45 // -----------------------------------------------------------------------------
46 // %_ConstructDouble
47
48
49 TEST_F(JSIntrinsicLoweringTest, InlineOptimizedConstructDouble) {
50   Node* const input0 = Parameter(0);
51   Node* const input1 = Parameter(1);
52   Node* const context = Parameter(2);
53   Node* const effect = graph()->start();
54   Node* const control = graph()->start();
55   Reduction const r = Reduce(graph()->NewNode(
56       javascript()->CallRuntime(Runtime::kInlineConstructDouble, 2), input0,
57       input1, context, effect, control));
58   ASSERT_TRUE(r.Changed());
59   EXPECT_THAT(r.replacement(), IsFloat64InsertHighWord32(
60                                    IsFloat64InsertLowWord32(
61                                        IsNumberConstant(BitEq(0.0)), input1),
62                                    input0));
63 }
64
65
66 // -----------------------------------------------------------------------------
67 // %_DoubleLo
68
69
70 TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleLo) {
71   Node* const input = Parameter(0);
72   Node* const context = Parameter(1);
73   Node* const effect = graph()->start();
74   Node* const control = graph()->start();
75   Reduction const r = Reduce(
76       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleLo, 1),
77                        input, context, effect, control));
78   ASSERT_TRUE(r.Changed());
79   EXPECT_THAT(r.replacement(), IsFloat64ExtractLowWord32(input));
80 }
81
82
83 // -----------------------------------------------------------------------------
84 // %_DoubleHi
85
86
87 TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleHi) {
88   Node* const input = Parameter(0);
89   Node* const context = Parameter(1);
90   Node* const effect = graph()->start();
91   Node* const control = graph()->start();
92   Reduction const r = Reduce(
93       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleHi, 1),
94                        input, context, effect, control));
95   ASSERT_TRUE(r.Changed());
96   EXPECT_THAT(r.replacement(), IsFloat64ExtractHighWord32(input));
97 }
98
99
100 // -----------------------------------------------------------------------------
101 // %_IsSmi
102
103
104 TEST_F(JSIntrinsicLoweringTest, InlineIsSmi) {
105   Node* const input = Parameter(0);
106   Node* const context = Parameter(1);
107   Node* const effect = graph()->start();
108   Node* const control = graph()->start();
109   Reduction const r = Reduce(
110       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1),
111                        input, context, effect, control));
112   ASSERT_TRUE(r.Changed());
113   EXPECT_THAT(r.replacement(), IsObjectIsSmi(input));
114 }
115
116
117 // -----------------------------------------------------------------------------
118 // %_IsNonNegativeSmi
119
120
121 TEST_F(JSIntrinsicLoweringTest, InlineIsNonNegativeSmi) {
122   Node* const input = Parameter(0);
123   Node* const context = Parameter(1);
124   Node* const effect = graph()->start();
125   Node* const control = graph()->start();
126   Reduction const r = Reduce(graph()->NewNode(
127       javascript()->CallRuntime(Runtime::kInlineIsNonNegativeSmi, 1), input,
128       context, effect, control));
129   ASSERT_TRUE(r.Changed());
130   EXPECT_THAT(r.replacement(), IsObjectIsNonNegativeSmi(input));
131 }
132
133
134 // -----------------------------------------------------------------------------
135 // %_IsArray
136
137
138 TEST_F(JSIntrinsicLoweringTest, InlineIsArray) {
139   Node* const input = Parameter(0);
140   Node* const context = Parameter(1);
141   Node* const effect = graph()->start();
142   Node* const control = graph()->start();
143   Reduction const r = Reduce(
144       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsArray, 1),
145                        input, context, effect, control));
146   ASSERT_TRUE(r.Changed());
147
148   Node* phi = r.replacement();
149   Capture<Node*> branch, if_false;
150   EXPECT_THAT(
151       phi,
152       IsPhi(
153           static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(),
154           IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
155                                     IsLoadField(AccessBuilder::ForMap(), input,
156                                                 effect, CaptureEq(&if_false)),
157                                     effect, _),
158                         IsInt32Constant(JS_ARRAY_TYPE)),
159           IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
160                                  IsBranch(IsObjectIsSmi(input), control))),
161                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
162 }
163
164
165 // -----------------------------------------------------------------------------
166 // %_IsFunction
167
168
169 TEST_F(JSIntrinsicLoweringTest, InlineIsFunction) {
170   Node* const input = Parameter(0);
171   Node* const context = Parameter(1);
172   Node* const effect = graph()->start();
173   Node* const control = graph()->start();
174   Reduction const r = Reduce(
175       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsFunction, 1),
176                        input, context, effect, control));
177   ASSERT_TRUE(r.Changed());
178
179   Node* phi = r.replacement();
180   Capture<Node*> branch, if_false;
181   EXPECT_THAT(
182       phi,
183       IsPhi(
184           static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(),
185           IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
186                                     IsLoadField(AccessBuilder::ForMap(), input,
187                                                 effect, CaptureEq(&if_false)),
188                                     effect, _),
189                         IsInt32Constant(JS_FUNCTION_TYPE)),
190           IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
191                                  IsBranch(IsObjectIsSmi(input), control))),
192                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
193 }
194
195
196 // -----------------------------------------------------------------------------
197 // %_IsRegExp
198
199
200 TEST_F(JSIntrinsicLoweringTest, InlineIsRegExp) {
201   Node* const input = Parameter(0);
202   Node* const context = Parameter(1);
203   Node* const effect = graph()->start();
204   Node* const control = graph()->start();
205   Reduction const r = Reduce(
206       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsRegExp, 1),
207                        input, context, effect, control));
208   ASSERT_TRUE(r.Changed());
209
210   Node* phi = r.replacement();
211   Capture<Node*> branch, if_false;
212   EXPECT_THAT(
213       phi,
214       IsPhi(
215           static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(),
216           IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
217                                     IsLoadField(AccessBuilder::ForMap(), input,
218                                                 effect, CaptureEq(&if_false)),
219                                     effect, _),
220                         IsInt32Constant(JS_REGEXP_TYPE)),
221           IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
222                                  IsBranch(IsObjectIsSmi(input), control))),
223                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
224 }
225
226
227 // -----------------------------------------------------------------------------
228 // %_JSValueGetValue
229
230
231 TEST_F(JSIntrinsicLoweringTest, InlineJSValueGetValue) {
232   Node* const input = Parameter(0);
233   Node* const context = Parameter(1);
234   Node* const effect = graph()->start();
235   Node* const control = graph()->start();
236   Reduction const r = Reduce(graph()->NewNode(
237       javascript()->CallRuntime(Runtime::kInlineJSValueGetValue, 1), input,
238       context, effect, control));
239   ASSERT_TRUE(r.Changed());
240   EXPECT_THAT(r.replacement(),
241               IsLoadField(AccessBuilder::ForValue(), input, effect, control));
242 }
243
244
245 // -----------------------------------------------------------------------------
246 // %_MathFloor
247
248
249 TEST_F(JSIntrinsicLoweringTest, InlineMathFloor) {
250   Node* const input = Parameter(0);
251   Node* const context = Parameter(1);
252   Node* const effect = graph()->start();
253   Node* const control = graph()->start();
254   Reduction const r = Reduce(
255       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineMathFloor, 1),
256                        input, context, effect, control),
257       MachineOperatorBuilder::kFloat64RoundDown);
258   ASSERT_TRUE(r.Changed());
259   EXPECT_THAT(r.replacement(), IsFloat64RoundDown(input));
260 }
261
262
263 // -----------------------------------------------------------------------------
264 // %_MathSqrt
265
266
267 TEST_F(JSIntrinsicLoweringTest, InlineMathSqrt) {
268   Node* const input = Parameter(0);
269   Node* const context = Parameter(1);
270   Node* const effect = graph()->start();
271   Node* const control = graph()->start();
272   Reduction const r = Reduce(
273       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineMathSqrt, 1),
274                        input, context, effect, control));
275   ASSERT_TRUE(r.Changed());
276   EXPECT_THAT(r.replacement(), IsFloat64Sqrt(input));
277 }
278
279
280 // -----------------------------------------------------------------------------
281 // %_StringGetLength
282
283
284 TEST_F(JSIntrinsicLoweringTest, InlineStringGetLength) {
285   Node* const input = Parameter(0);
286   Node* const context = Parameter(1);
287   Node* const effect = graph()->start();
288   Node* const control = graph()->start();
289   Reduction const r = Reduce(graph()->NewNode(
290       javascript()->CallRuntime(Runtime::kInlineStringGetLength, 1), input,
291       context, effect, control));
292   ASSERT_TRUE(r.Changed());
293   EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
294                                            input, effect, control));
295 }
296
297
298 // -----------------------------------------------------------------------------
299 // %_MathClz32
300
301
302 TEST_F(JSIntrinsicLoweringTest, InlineMathClz32) {
303   Node* const input = Parameter(0);
304   Node* const context = Parameter(1);
305   Node* const effect = graph()->start();
306   Node* const control = graph()->start();
307   Reduction const r = Reduce(
308       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineMathClz32, 1),
309                        input, context, effect, control));
310   ASSERT_TRUE(r.Changed());
311   EXPECT_THAT(r.replacement(), IsWord32Clz(input));
312 }
313
314
315 // -----------------------------------------------------------------------------
316 // %_ValueOf
317
318
319 TEST_F(JSIntrinsicLoweringTest, InlineValueOf) {
320   Node* const input = Parameter(0);
321   Node* const context = Parameter(1);
322   Node* const effect = graph()->start();
323   Node* const control = graph()->start();
324   Reduction const r = Reduce(
325       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineValueOf, 1),
326                        input, context, effect, control));
327   ASSERT_TRUE(r.Changed());
328
329   Node* phi = r.replacement();
330   Capture<Node*> branch0, if_false0, branch1, if_true1;
331   EXPECT_THAT(
332       phi,
333       IsPhi(
334           kMachAnyTagged, input,
335           IsPhi(kMachAnyTagged, IsLoadField(AccessBuilder::ForValue(), input,
336                                             effect, CaptureEq(&if_true1)),
337                 input,
338                 IsMerge(
339                     AllOf(CaptureEq(&if_true1), IsIfTrue(CaptureEq(&branch1))),
340                     IsIfFalse(AllOf(
341                         CaptureEq(&branch1),
342                         IsBranch(
343                             IsWord32Equal(
344                                 IsLoadField(
345                                     AccessBuilder::ForMapInstanceType(),
346                                     IsLoadField(AccessBuilder::ForMap(), input,
347                                                 effect, CaptureEq(&if_false0)),
348                                     effect, _),
349                                 IsInt32Constant(JS_VALUE_TYPE)),
350                             CaptureEq(&if_false0)))))),
351           IsMerge(
352               IsIfTrue(AllOf(CaptureEq(&branch0),
353                              IsBranch(IsObjectIsSmi(input), control))),
354               AllOf(CaptureEq(&if_false0), IsIfFalse(CaptureEq(&branch0))))));
355 }
356
357 }  // namespace compiler
358 }  // namespace internal
359 }  // namespace v8