blob: 7024559a117f68f1f167baafe4d1d1e97f63dab4 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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/diamond.h"
7#include "src/compiler/js-graph.h"
8#include "src/compiler/js-intrinsic-lowering.h"
9#include "src/compiler/js-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "test/unittests/compiler/graph-unittest.h"
11#include "test/unittests/compiler/node-test-utils.h"
12#include "testing/gmock-support.h"
13
14
15using testing::_;
16using testing::AllOf;
17using testing::BitEq;
18using testing::Capture;
19using testing::CaptureEq;
20
21
22namespace v8 {
23namespace internal {
24namespace compiler {
25
Ben Murdoch097c5b22016-05-18 11:27:45 +010026class JSIntrinsicLoweringTest : public GraphTest {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +010028 JSIntrinsicLoweringTest() : GraphTest(3), javascript_(zone()) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 ~JSIntrinsicLoweringTest() override {}
30
31 protected:
32 Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
33 MachineOperatorBuilder::kNoFlags) {
34 MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
35 flags);
36 SimplifiedOperatorBuilder simplified(zone());
37 JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
38 &machine);
39 // TODO(titzer): mock the GraphReducer here for better unit testing.
40 GraphReducer graph_reducer(zone(), graph());
41 JSIntrinsicLowering reducer(&graph_reducer, &jsgraph,
42 JSIntrinsicLowering::kDeoptimizationEnabled);
43 return reducer.Reduce(node);
44 }
45
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046 JSOperatorBuilder* javascript() { return &javascript_; }
47
48 private:
49 JSOperatorBuilder javascript_;
50};
51
52
53// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054// %_DoubleLo
55
56
57TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleLo) {
58 Node* const input = Parameter(0);
59 Node* const context = Parameter(1);
60 Node* const effect = graph()->start();
61 Node* const control = graph()->start();
62 Reduction const r = Reduce(
63 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleLo, 1),
64 input, context, effect, control));
65 ASSERT_TRUE(r.Changed());
Ben Murdochda12d292016-06-02 14:46:10 +010066 EXPECT_THAT(r.replacement(),
Ben Murdochc5610432016-08-08 18:44:38 +010067 IsFloat64ExtractLowWord32(IsTypeGuard(Type::Number(), input, _)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068}
69
70
71// -----------------------------------------------------------------------------
72// %_DoubleHi
73
74
75TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleHi) {
76 Node* const input = Parameter(0);
77 Node* const context = Parameter(1);
78 Node* const effect = graph()->start();
79 Node* const control = graph()->start();
80 Reduction const r = Reduce(
81 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleHi, 1),
82 input, context, effect, control));
83 ASSERT_TRUE(r.Changed());
Ben Murdochc5610432016-08-08 18:44:38 +010084 EXPECT_THAT(r.replacement(), IsFloat64ExtractHighWord32(
85 IsTypeGuard(Type::Number(), input, _)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086}
87
88
89// -----------------------------------------------------------------------------
90// %_IsSmi
91
92
93TEST_F(JSIntrinsicLoweringTest, InlineIsSmi) {
94 Node* const input = Parameter(0);
95 Node* const context = Parameter(1);
96 Node* const effect = graph()->start();
97 Node* const control = graph()->start();
98 Reduction const r = Reduce(
99 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1),
100 input, context, effect, control));
101 ASSERT_TRUE(r.Changed());
102 EXPECT_THAT(r.replacement(), IsObjectIsSmi(input));
103}
104
105
106// -----------------------------------------------------------------------------
107// %_IsArray
108
109
110TEST_F(JSIntrinsicLoweringTest, InlineIsArray) {
111 Node* const input = Parameter(0);
112 Node* const context = Parameter(1);
113 Node* const effect = graph()->start();
114 Node* const control = graph()->start();
115 Reduction const r = Reduce(
116 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsArray, 1),
117 input, context, effect, control));
118 ASSERT_TRUE(r.Changed());
119
120 Node* phi = r.replacement();
121 Capture<Node*> branch, if_false;
122 EXPECT_THAT(
123 phi,
124 IsPhi(
125 MachineRepresentation::kTagged, IsFalseConstant(),
126 IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
127 IsLoadField(AccessBuilder::ForMap(), input,
128 effect, CaptureEq(&if_false)),
129 effect, _),
130 IsInt32Constant(JS_ARRAY_TYPE)),
131 IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
132 IsBranch(IsObjectIsSmi(input), control))),
133 AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
134}
135
136
137// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138// %_IsTypedArray
139
140
141TEST_F(JSIntrinsicLoweringTest, InlineIsTypedArray) {
142 Node* const input = Parameter(0);
143 Node* const context = Parameter(1);
144 Node* const effect = graph()->start();
145 Node* const control = graph()->start();
146 Reduction const r = Reduce(graph()->NewNode(
147 javascript()->CallRuntime(Runtime::kInlineIsTypedArray, 1), input,
148 context, effect, control));
149 ASSERT_TRUE(r.Changed());
150
151 Node* phi = r.replacement();
152 Capture<Node*> branch, if_false;
153 EXPECT_THAT(
154 phi,
155 IsPhi(
156 MachineRepresentation::kTagged, IsFalseConstant(),
157 IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
158 IsLoadField(AccessBuilder::ForMap(), input,
159 effect, CaptureEq(&if_false)),
160 effect, _),
161 IsInt32Constant(JS_TYPED_ARRAY_TYPE)),
162 IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
163 IsBranch(IsObjectIsSmi(input), control))),
164 AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
165}
166
167
168// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169// %_IsRegExp
170
171
172TEST_F(JSIntrinsicLoweringTest, InlineIsRegExp) {
173 Node* const input = Parameter(0);
174 Node* const context = Parameter(1);
175 Node* const effect = graph()->start();
176 Node* const control = graph()->start();
177 Reduction const r = Reduce(
178 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsRegExp, 1),
179 input, context, effect, control));
180 ASSERT_TRUE(r.Changed());
181
182 Node* phi = r.replacement();
183 Capture<Node*> branch, if_false;
184 EXPECT_THAT(
185 phi,
186 IsPhi(
187 MachineRepresentation::kTagged, IsFalseConstant(),
188 IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
189 IsLoadField(AccessBuilder::ForMap(), input,
190 effect, CaptureEq(&if_false)),
191 effect, _),
192 IsInt32Constant(JS_REGEXP_TYPE)),
193 IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
194 IsBranch(IsObjectIsSmi(input), control))),
195 AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
196}
197
198
199// -----------------------------------------------------------------------------
200// %_IsJSReceiver
201
202
Ben Murdoch097c5b22016-05-18 11:27:45 +0100203TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiver) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 Node* const input = Parameter(0);
205 Node* const context = Parameter(1);
206 Node* const effect = graph()->start();
207 Node* const control = graph()->start();
208 Reduction const r = Reduce(graph()->NewNode(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100209 javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 context, effect, control));
211 ASSERT_TRUE(r.Changed());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100212 EXPECT_THAT(r.replacement(), IsObjectIsReceiver(input));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213}
214
215
216// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217// %_ValueOf
218
219
220TEST_F(JSIntrinsicLoweringTest, InlineValueOf) {
221 Node* const input = Parameter(0);
222 Node* const context = Parameter(1);
223 Node* const effect = graph()->start();
224 Node* const control = graph()->start();
225 Reduction const r = Reduce(
226 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineValueOf, 1),
227 input, context, effect, control));
228 ASSERT_TRUE(r.Changed());
229
230 Node* phi = r.replacement();
231 Capture<Node*> branch0, if_false0, branch1, if_true1;
232 EXPECT_THAT(
233 phi,
234 IsPhi(
235 MachineRepresentation::kTagged, input,
236 IsPhi(MachineRepresentation::kTagged,
237 IsLoadField(AccessBuilder::ForValue(), input, effect,
238 CaptureEq(&if_true1)),
239 input,
240 IsMerge(
241 AllOf(CaptureEq(&if_true1), IsIfTrue(CaptureEq(&branch1))),
242 IsIfFalse(AllOf(
243 CaptureEq(&branch1),
244 IsBranch(
245 IsWord32Equal(
246 IsLoadField(
247 AccessBuilder::ForMapInstanceType(),
248 IsLoadField(AccessBuilder::ForMap(), input,
249 effect, CaptureEq(&if_false0)),
250 effect, _),
251 IsInt32Constant(JS_VALUE_TYPE)),
252 CaptureEq(&if_false0)))))),
253 IsMerge(
254 IsIfTrue(AllOf(CaptureEq(&branch0),
255 IsBranch(IsObjectIsSmi(input), control))),
256 AllOf(CaptureEq(&if_false0), IsIfFalse(CaptureEq(&branch0))))));
257}
258
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259} // namespace compiler
260} // namespace internal
261} // namespace v8