blob: 7c2f45942ce0893834233eb5ba7f8dafe4af988e [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
46 Node* EmptyFrameState() {
47 MachineOperatorBuilder machine(zone());
48 JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
49 &machine);
50 return jsgraph.EmptyFrameState();
51 }
52
53 JSOperatorBuilder* javascript() { return &javascript_; }
54
55 private:
56 JSOperatorBuilder javascript_;
57};
58
59
60// -----------------------------------------------------------------------------
61// %_ConstructDouble
62
63
64TEST_F(JSIntrinsicLoweringTest, InlineOptimizedConstructDouble) {
65 Node* const input0 = Parameter(0);
66 Node* const input1 = Parameter(1);
67 Node* const context = Parameter(2);
68 Node* const effect = graph()->start();
69 Node* const control = graph()->start();
70 Reduction const r = Reduce(graph()->NewNode(
71 javascript()->CallRuntime(Runtime::kInlineConstructDouble, 2), input0,
72 input1, context, effect, control));
73 ASSERT_TRUE(r.Changed());
74 EXPECT_THAT(r.replacement(), IsFloat64InsertHighWord32(
75 IsFloat64InsertLowWord32(
76 IsNumberConstant(BitEq(0.0)), input1),
77 input0));
78}
79
80
81// -----------------------------------------------------------------------------
82// %_DoubleLo
83
84
85TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleLo) {
86 Node* const input = Parameter(0);
87 Node* const context = Parameter(1);
88 Node* const effect = graph()->start();
89 Node* const control = graph()->start();
90 Reduction const r = Reduce(
91 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleLo, 1),
92 input, context, effect, control));
93 ASSERT_TRUE(r.Changed());
Ben Murdochda12d292016-06-02 14:46:10 +010094 EXPECT_THAT(r.replacement(),
Ben Murdochc5610432016-08-08 18:44:38 +010095 IsFloat64ExtractLowWord32(IsTypeGuard(Type::Number(), input, _)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096}
97
98
99// -----------------------------------------------------------------------------
100// %_DoubleHi
101
102
103TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleHi) {
104 Node* const input = Parameter(0);
105 Node* const context = Parameter(1);
106 Node* const effect = graph()->start();
107 Node* const control = graph()->start();
108 Reduction const r = Reduce(
109 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleHi, 1),
110 input, context, effect, control));
111 ASSERT_TRUE(r.Changed());
Ben Murdochc5610432016-08-08 18:44:38 +0100112 EXPECT_THAT(r.replacement(), IsFloat64ExtractHighWord32(
113 IsTypeGuard(Type::Number(), input, _)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114}
115
116
117// -----------------------------------------------------------------------------
118// %_IsSmi
119
120
121TEST_F(JSIntrinsicLoweringTest, InlineIsSmi) {
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(
127 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1),
128 input, context, effect, control));
129 ASSERT_TRUE(r.Changed());
130 EXPECT_THAT(r.replacement(), IsObjectIsSmi(input));
131}
132
133
134// -----------------------------------------------------------------------------
135// %_IsArray
136
137
138TEST_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 MachineRepresentation::kTagged, 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// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166// %_IsTypedArray
167
168
169TEST_F(JSIntrinsicLoweringTest, InlineIsTypedArray) {
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(graph()->NewNode(
175 javascript()->CallRuntime(Runtime::kInlineIsTypedArray, 1), input,
176 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 MachineRepresentation::kTagged, IsFalseConstant(),
185 IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
186 IsLoadField(AccessBuilder::ForMap(), input,
187 effect, CaptureEq(&if_false)),
188 effect, _),
189 IsInt32Constant(JS_TYPED_ARRAY_TYPE)),
190 IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
191 IsBranch(IsObjectIsSmi(input), control))),
192 AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
193}
194
195
196// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197// %_IsRegExp
198
199
200TEST_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 MachineRepresentation::kTagged, 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// %_IsJSReceiver
229
230
Ben Murdoch097c5b22016-05-18 11:27:45 +0100231TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiver) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 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(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100237 javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 context, effect, control));
239 ASSERT_TRUE(r.Changed());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100240 EXPECT_THAT(r.replacement(), IsObjectIsReceiver(input));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241}
242
243
244// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245// %_ValueOf
246
247
248TEST_F(JSIntrinsicLoweringTest, InlineValueOf) {
249 Node* const input = Parameter(0);
250 Node* const context = Parameter(1);
251 Node* const effect = graph()->start();
252 Node* const control = graph()->start();
253 Reduction const r = Reduce(
254 graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineValueOf, 1),
255 input, context, effect, control));
256 ASSERT_TRUE(r.Changed());
257
258 Node* phi = r.replacement();
259 Capture<Node*> branch0, if_false0, branch1, if_true1;
260 EXPECT_THAT(
261 phi,
262 IsPhi(
263 MachineRepresentation::kTagged, input,
264 IsPhi(MachineRepresentation::kTagged,
265 IsLoadField(AccessBuilder::ForValue(), input, effect,
266 CaptureEq(&if_true1)),
267 input,
268 IsMerge(
269 AllOf(CaptureEq(&if_true1), IsIfTrue(CaptureEq(&branch1))),
270 IsIfFalse(AllOf(
271 CaptureEq(&branch1),
272 IsBranch(
273 IsWord32Equal(
274 IsLoadField(
275 AccessBuilder::ForMapInstanceType(),
276 IsLoadField(AccessBuilder::ForMap(), input,
277 effect, CaptureEq(&if_false0)),
278 effect, _),
279 IsInt32Constant(JS_VALUE_TYPE)),
280 CaptureEq(&if_false0)))))),
281 IsMerge(
282 IsIfTrue(AllOf(CaptureEq(&branch0),
283 IsBranch(IsObjectIsSmi(input), control))),
284 AllOf(CaptureEq(&if_false0), IsIfFalse(CaptureEq(&branch0))))));
285}
286
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287} // namespace compiler
288} // namespace internal
289} // namespace v8