blob: 6fc89bb0ea44bc1b19bd2f40a95515feb3764e36 [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/code-factory.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006#include "src/compiler/access-builder.h"
7#include "src/compiler/js-graph.h"
8#include "src/compiler/js-operator.h"
9#include "src/compiler/js-typed-lowering.h"
10#include "src/compiler/machine-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/compiler/node-properties.h"
12#include "src/compiler/operator-properties.h"
13#include "src/isolate-inl.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014#include "test/unittests/compiler/compiler-test-utils.h"
15#include "test/unittests/compiler/graph-unittest.h"
16#include "test/unittests/compiler/node-test-utils.h"
17#include "testing/gmock-support.h"
18
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019using testing::_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020using testing::BitEq;
21using testing::IsNaN;
22
23
24namespace v8 {
25namespace internal {
26namespace compiler {
27
28namespace {
29
30const ExternalArrayType kExternalArrayTypes[] = {
31 kExternalUint8Array, kExternalInt8Array, kExternalUint16Array,
32 kExternalInt16Array, kExternalUint32Array, kExternalInt32Array,
33 kExternalFloat32Array, kExternalFloat64Array};
34
35
36const double kFloat64Values[] = {
37 -V8_INFINITY, -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212,
38 -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100,
39 -1.67813e+72, -2.3382e+55, -3.179e+30, -1.441e+09, -1.0647e+09,
40 -7.99361e+08, -5.77375e+08, -2.20984e+08, -32757, -13171, -9970, -3984,
41 -107, -105, -92, -77, -61, -0.000208163, -1.86685e-06, -1.17296e-10,
42 -9.26358e-11, -5.08004e-60, -1.74753e-65, -1.06561e-71, -5.67879e-79,
43 -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
44 -4.40497e-267, -2.19666e-273, -4.9998e-276, -5.59821e-278, -2.03855e-282,
45 -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0, 0.0, 2.22507e-308,
46 1.30127e-270, 7.62898e-260, 4.00313e-249, 3.16829e-233, 1.85244e-228,
47 2.03544e-129, 1.35126e-110, 1.01182e-106, 5.26333e-94, 1.35292e-90,
48 2.85394e-83, 1.78323e-77, 5.4967e-57, 1.03207e-25, 4.57401e-25, 1.58738e-05,
49 2, 125, 2310, 9636, 14802, 17168, 28945, 29305, 4.81336e+07, 1.41207e+08,
50 4.65962e+08, 1.40499e+09, 2.12648e+09, 8.80006e+30, 1.4446e+45, 1.12164e+54,
51 2.48188e+89, 6.71121e+102, 3.074e+112, 4.9699e+152, 5.58383e+166,
52 4.30654e+172, 7.08824e+185, 9.6586e+214, 2.028e+223, 6.63277e+243,
53 1.56192e+261, 1.23202e+269, 5.72883e+289, 8.5798e+290, 1.40256e+294,
54 1.79769e+308, V8_INFINITY};
55
56
57const size_t kIndices[] = {0, 1, 42, 100, 1024};
58
59
60const double kIntegerValues[] = {-V8_INFINITY, INT_MIN, -1000.0, -42.0,
61 -1.0, 0.0, 1.0, 42.0,
62 1000.0, INT_MAX, UINT_MAX, V8_INFINITY};
63
64
65Type* const kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(),
66 Type::Number(), Type::String(), Type::Object()};
67
68
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069STATIC_ASSERT(LANGUAGE_END == 3);
70const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040071
72} // namespace
73
74
75class JSTypedLoweringTest : public TypedGraphTest {
76 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 JSTypedLoweringTest()
78 : TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {}
79 ~JSTypedLoweringTest() override {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080
81 protected:
82 Reduction Reduce(Node* node) {
83 MachineOperatorBuilder machine(zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 SimplifiedOperatorBuilder simplified(zone());
85 JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
86 &machine);
87 // TODO(titzer): mock the GraphReducer here for better unit testing.
88 GraphReducer graph_reducer(zone(), graph());
89 JSTypedLowering reducer(&graph_reducer, &deps_,
90 JSTypedLowering::kDeoptimizationEnabled, &jsgraph,
91 zone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040092 return reducer.Reduce(node);
93 }
94
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 Node* FrameState(Handle<SharedFunctionInfo> shared, Node* outer_frame_state) {
96 Node* state_values = graph()->NewNode(common()->StateValues(0));
97 return graph()->NewNode(
98 common()->FrameState(BailoutId::None(),
99 OutputFrameStateCombine::Ignore(),
100 common()->CreateFrameStateFunctionInfo(
101 FrameStateType::kJavaScriptFunction, 1, 0,
102 shared, CALL_MAINTAINS_NATIVE_CONTEXT)),
103 state_values, state_values, state_values, NumberConstant(0),
104 UndefinedConstant(), outer_frame_state);
105 }
106
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400107 Handle<JSArrayBuffer> NewArrayBuffer(void* bytes, size_t byte_length) {
108 Handle<JSArrayBuffer> buffer = factory()->NewJSArrayBuffer();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 JSArrayBuffer::Setup(buffer, isolate(), true, bytes, byte_length);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400110 return buffer;
111 }
112
113 Matcher<Node*> IsIntPtrConstant(intptr_t value) {
114 return sizeof(value) == 4 ? IsInt32Constant(static_cast<int32_t>(value))
115 : IsInt64Constant(static_cast<int64_t>(value));
116 }
117
118 JSOperatorBuilder* javascript() { return &javascript_; }
119
120 private:
121 JSOperatorBuilder javascript_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 CompilationDependencies deps_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123};
124
125
126// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400127// Constant propagation
128
129
130TEST_F(JSTypedLoweringTest, ParameterWithMinusZero) {
131 {
132 Reduction r = Reduce(
133 Parameter(Type::Constant(factory()->minus_zero_value(), zone())));
134 ASSERT_TRUE(r.Changed());
135 EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
136 }
137 {
138 Reduction r = Reduce(Parameter(Type::MinusZero()));
139 ASSERT_TRUE(r.Changed());
140 EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
141 }
142 {
143 Reduction r = Reduce(Parameter(
144 Type::Union(Type::MinusZero(),
145 Type::Constant(factory()->NewNumber(0), zone()), zone())));
146 EXPECT_FALSE(r.Changed());
147 }
148}
149
150
151TEST_F(JSTypedLoweringTest, ParameterWithNull) {
152 Handle<HeapObject> null = factory()->null_value();
153 {
154 Reduction r = Reduce(Parameter(Type::Constant(null, zone())));
155 ASSERT_TRUE(r.Changed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 EXPECT_THAT(r.replacement(), IsHeapConstant(null));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400157 }
158 {
159 Reduction r = Reduce(Parameter(Type::Null()));
160 ASSERT_TRUE(r.Changed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 EXPECT_THAT(r.replacement(), IsHeapConstant(null));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400162 }
163}
164
165
166TEST_F(JSTypedLoweringTest, ParameterWithNaN) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168 std::numeric_limits<double>::quiet_NaN(),
169 std::numeric_limits<double>::signaling_NaN()};
170 TRACED_FOREACH(double, nan, kNaNs) {
171 Handle<Object> constant = factory()->NewNumber(nan);
172 Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
173 ASSERT_TRUE(r.Changed());
174 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
175 }
176 {
177 Reduction r =
178 Reduce(Parameter(Type::Constant(factory()->nan_value(), zone())));
179 ASSERT_TRUE(r.Changed());
180 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
181 }
182 {
183 Reduction r = Reduce(Parameter(Type::NaN()));
184 ASSERT_TRUE(r.Changed());
185 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
186 }
187}
188
189
190TEST_F(JSTypedLoweringTest, ParameterWithPlainNumber) {
191 TRACED_FOREACH(double, value, kFloat64Values) {
192 Handle<Object> constant = factory()->NewNumber(value);
193 Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
194 ASSERT_TRUE(r.Changed());
195 EXPECT_THAT(r.replacement(), IsNumberConstant(value));
196 }
197 TRACED_FOREACH(double, value, kIntegerValues) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 Reduction r = Reduce(Parameter(Type::Range(value, value, zone())));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 ASSERT_TRUE(r.Changed());
200 EXPECT_THAT(r.replacement(), IsNumberConstant(value));
201 }
202}
203
204
205TEST_F(JSTypedLoweringTest, ParameterWithUndefined) {
206 Handle<HeapObject> undefined = factory()->undefined_value();
207 {
208 Reduction r = Reduce(Parameter(Type::Undefined()));
209 ASSERT_TRUE(r.Changed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211 }
212 {
213 Reduction r = Reduce(Parameter(Type::Constant(undefined, zone())));
214 ASSERT_TRUE(r.Changed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400216 }
217}
218
219
220// -----------------------------------------------------------------------------
221// JSToBoolean
222
223
224TEST_F(JSTypedLoweringTest, JSToBooleanWithBoolean) {
225 Node* input = Parameter(Type::Boolean(), 0);
226 Node* context = Parameter(Type::Any(), 1);
227 Reduction r =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
229 input, context, graph()->start()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400230 ASSERT_TRUE(r.Changed());
231 EXPECT_EQ(input, r.replacement());
232}
233
234
235TEST_F(JSTypedLoweringTest, JSToBooleanWithFalsish) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400236 Node* input = Parameter(
237 Type::Union(
238 Type::MinusZero(),
239 Type::Union(
240 Type::NaN(),
241 Type::Union(
242 Type::Null(),
243 Type::Union(
244 Type::Undefined(),
245 Type::Union(
246 Type::Undetectable(),
247 Type::Union(
248 Type::Constant(factory()->false_value(), zone()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 Type::Range(0.0, 0.0, zone()), zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400250 zone()),
251 zone()),
252 zone()),
253 zone()),
254 zone()),
255 0);
256 Node* context = Parameter(Type::Any(), 1);
257 Reduction r =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
259 input, context, graph()->start()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400260 ASSERT_TRUE(r.Changed());
261 EXPECT_THAT(r.replacement(), IsFalseConstant());
262}
263
264
265TEST_F(JSTypedLoweringTest, JSToBooleanWithTruish) {
266 Node* input = Parameter(
267 Type::Union(
268 Type::Constant(factory()->true_value(), zone()),
269 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
270 zone()),
271 0);
272 Node* context = Parameter(Type::Any(), 1);
273 Reduction r =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
275 input, context, graph()->start()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400276 ASSERT_TRUE(r.Changed());
277 EXPECT_THAT(r.replacement(), IsTrueConstant());
278}
279
280
281TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400283 Node* context = Parameter(Type::Any(), 1);
284 Reduction r =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
286 input, context, graph()->start()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400287 ASSERT_TRUE(r.Changed());
288 EXPECT_THAT(r.replacement(), IsTrueConstant());
289}
290
291
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) {
293 Node* input = Parameter(Type::OrderedNumber(), 0);
294 Node* context = Parameter(Type::Any(), 1);
295 Reduction r =
296 Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
297 input, context, graph()->start()));
298 ASSERT_TRUE(r.Changed());
299 EXPECT_THAT(r.replacement(),
300 IsBooleanNot(IsNumberEqual(input, IsNumberConstant(0.0))));
301}
302
303
304TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
305 Node* input = Parameter(Type::String(), 0);
306 Node* context = Parameter(Type::Any(), 1);
307 Reduction r =
308 Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
309 input, context, graph()->start()));
310 ASSERT_TRUE(r.Changed());
311 EXPECT_THAT(
312 r.replacement(),
313 IsNumberLessThan(IsNumberConstant(0.0),
314 IsLoadField(AccessBuilder::ForStringLength(), input,
315 graph()->start(), graph()->start())));
316}
317
318
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400319TEST_F(JSTypedLoweringTest, JSToBooleanWithAny) {
320 Node* input = Parameter(Type::Any(), 0);
321 Node* context = Parameter(Type::Any(), 1);
322 Reduction r =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323 Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
324 input, context, graph()->start()));
325 ASSERT_FALSE(r.Changed());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400326}
327
328
329// -----------------------------------------------------------------------------
330// JSToNumber
331
332
333TEST_F(JSTypedLoweringTest, JSToNumberWithPlainPrimitive) {
334 Node* const input = Parameter(Type::PlainPrimitive(), 0);
335 Node* const context = Parameter(Type::Any(), 1);
336 Node* const effect = graph()->start();
337 Node* const control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 Reduction r =
339 Reduce(graph()->NewNode(javascript()->ToNumber(), input, context,
340 EmptyFrameState(), effect, control));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341 ASSERT_TRUE(r.Changed());
342 EXPECT_THAT(r.replacement(), IsToNumber(input, IsNumberConstant(BitEq(0.0)),
343 graph()->start(), control));
344}
345
346
347// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348// JSToObject
349
350
351TEST_F(JSTypedLoweringTest, JSToObjectWithAny) {
352 Node* const input = Parameter(Type::Any(), 0);
353 Node* const context = Parameter(Type::Any(), 1);
354 Node* const frame_state = EmptyFrameState();
355 Node* const effect = graph()->start();
356 Node* const control = graph()->start();
357 Reduction r = Reduce(graph()->NewNode(javascript()->ToObject(), input,
358 context, frame_state, effect, control));
359 ASSERT_TRUE(r.Changed());
360 EXPECT_THAT(r.replacement(), IsPhi(MachineRepresentation::kTagged, _, _, _));
361}
362
363
364TEST_F(JSTypedLoweringTest, JSToObjectWithReceiver) {
365 Node* const input = Parameter(Type::Receiver(), 0);
366 Node* const context = Parameter(Type::Any(), 1);
367 Node* const frame_state = EmptyFrameState();
368 Node* const effect = graph()->start();
369 Node* const control = graph()->start();
370 Reduction r = Reduce(graph()->NewNode(javascript()->ToObject(), input,
371 context, frame_state, effect, control));
372 ASSERT_TRUE(r.Changed());
373 EXPECT_EQ(input, r.replacement());
374}
375
376
377// -----------------------------------------------------------------------------
378// JSToString
379
380
381TEST_F(JSTypedLoweringTest, JSToStringWithBoolean) {
382 Node* const input = Parameter(Type::Boolean(), 0);
383 Node* const context = Parameter(Type::Any(), 1);
384 Node* const frame_state = EmptyFrameState();
385 Node* const effect = graph()->start();
386 Node* const control = graph()->start();
387 Reduction r = Reduce(graph()->NewNode(javascript()->ToString(), input,
388 context, frame_state, effect, control));
389 ASSERT_TRUE(r.Changed());
390 EXPECT_THAT(r.replacement(),
391 IsSelect(MachineRepresentation::kTagged, input,
392 IsHeapConstant(factory()->true_string()),
393 IsHeapConstant(factory()->false_string())));
394}
395
396
397// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400398// JSStrictEqual
399
400
401TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) {
402 Node* const the_hole = HeapConstant(factory()->the_hole_value());
403 Node* const context = UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400404 TRACED_FOREACH(Type*, type, kJSTypes) {
405 Node* const lhs = Parameter(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 Reduction r =
407 Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole,
408 context, graph()->start(), graph()->start()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400409 ASSERT_TRUE(r.Changed());
410 EXPECT_THAT(r.replacement(), IsFalseConstant());
411 }
412}
413
414
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) {
416 Node* const lhs = Parameter(Type::Unique(), 0);
417 Node* const rhs = Parameter(Type::Unique(), 1);
418 Node* const context = Parameter(Type::Any(), 2);
419 Reduction r =
420 Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context,
421 graph()->start(), graph()->start()));
422 ASSERT_TRUE(r.Changed());
423 EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs));
424}
425
426
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400427// -----------------------------------------------------------------------------
428// JSShiftLeft
429
430
431TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400433 Node* const lhs = Parameter(Type::Signed32());
434 Node* const context = UndefinedConstant();
435 Node* const effect = graph()->start();
436 Node* const control = graph()->start();
437 TRACED_FORRANGE(double, rhs, 0, 31) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
439 Reduction r = Reduce(
440 graph()->NewNode(javascript()->ShiftLeft(language_mode, hints), lhs,
441 NumberConstant(rhs), context, EmptyFrameState(),
442 EmptyFrameState(), effect, control));
443 ASSERT_TRUE(r.Changed());
444 EXPECT_THAT(r.replacement(),
445 IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
446 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400447 }
448}
449
450
451TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400453 Node* const lhs = Parameter(Type::Signed32());
454 Node* const rhs = Parameter(Type::Unsigned32());
455 Node* const context = UndefinedConstant();
456 Node* const effect = graph()->start();
457 Node* const control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
459 Reduction r = Reduce(graph()->NewNode(
460 javascript()->ShiftLeft(language_mode, hints), lhs, rhs, context,
461 EmptyFrameState(), EmptyFrameState(), effect, control));
462 ASSERT_TRUE(r.Changed());
463 EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
464 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400465}
466
467
468// -----------------------------------------------------------------------------
469// JSShiftRight
470
471
472TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000473 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400474 Node* const lhs = Parameter(Type::Signed32());
475 Node* const context = UndefinedConstant();
476 Node* const effect = graph()->start();
477 Node* const control = graph()->start();
478 TRACED_FORRANGE(double, rhs, 0, 31) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
480 Reduction r = Reduce(
481 graph()->NewNode(javascript()->ShiftRight(language_mode, hints), lhs,
482 NumberConstant(rhs), context, EmptyFrameState(),
483 EmptyFrameState(), effect, control));
484 ASSERT_TRUE(r.Changed());
485 EXPECT_THAT(r.replacement(),
486 IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
487 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400488 }
489}
490
491
492TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000493 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400494 Node* const lhs = Parameter(Type::Signed32());
495 Node* const rhs = Parameter(Type::Unsigned32());
496 Node* const context = UndefinedConstant();
497 Node* const effect = graph()->start();
498 Node* const control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
500 Reduction r = Reduce(graph()->NewNode(
501 javascript()->ShiftRight(language_mode, hints), lhs, rhs, context,
502 EmptyFrameState(), EmptyFrameState(), effect, control));
503 ASSERT_TRUE(r.Changed());
504 EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
505 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400506}
507
508
509// -----------------------------------------------------------------------------
510// JSShiftRightLogical
511
512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513TEST_F(JSTypedLoweringTest,
514 JSShiftRightLogicalWithUnsigned32AndConstant) {
515 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400516 Node* const lhs = Parameter(Type::Unsigned32());
517 Node* const context = UndefinedConstant();
518 Node* const effect = graph()->start();
519 Node* const control = graph()->start();
520 TRACED_FORRANGE(double, rhs, 0, 31) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000521 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
522 Reduction r = Reduce(graph()->NewNode(
523 javascript()->ShiftRightLogical(language_mode, hints), lhs,
524 NumberConstant(rhs), context, EmptyFrameState(), EmptyFrameState(),
525 effect, control));
526 ASSERT_TRUE(r.Changed());
527 EXPECT_THAT(r.replacement(),
528 IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
529 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400530 }
531}
532
533
534TEST_F(JSTypedLoweringTest, JSShiftRightLogicalWithUnsigned32AndUnsigned32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000535 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400536 Node* const lhs = Parameter(Type::Unsigned32());
537 Node* const rhs = Parameter(Type::Unsigned32());
538 Node* const context = UndefinedConstant();
539 Node* const effect = graph()->start();
540 Node* const control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000541 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
542 Reduction r = Reduce(graph()->NewNode(
543 javascript()->ShiftRightLogical(language_mode, hints), lhs, rhs,
544 context, EmptyFrameState(), EmptyFrameState(), effect, control));
545 ASSERT_TRUE(r.Changed());
546 EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
547 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400548}
549
550
551// -----------------------------------------------------------------------------
552// JSLoadContext
553
554
555TEST_F(JSTypedLoweringTest, JSLoadContext) {
556 Node* const context = Parameter(Type::Any());
557 Node* const effect = graph()->start();
558 static bool kBooleans[] = {false, true};
559 TRACED_FOREACH(size_t, index, kIndices) {
560 TRACED_FOREACH(bool, immutable, kBooleans) {
561 Reduction const r1 = Reduce(
562 graph()->NewNode(javascript()->LoadContext(0, index, immutable),
563 context, context, effect));
564 ASSERT_TRUE(r1.Changed());
565 EXPECT_THAT(r1.replacement(),
566 IsLoadField(AccessBuilder::ForContextSlot(index), context,
567 effect, graph()->start()));
568
569 Reduction const r2 = Reduce(
570 graph()->NewNode(javascript()->LoadContext(1, index, immutable),
571 context, context, effect));
572 ASSERT_TRUE(r2.Changed());
573 EXPECT_THAT(r2.replacement(),
574 IsLoadField(AccessBuilder::ForContextSlot(index),
575 IsLoadField(AccessBuilder::ForContextSlot(
576 Context::PREVIOUS_INDEX),
577 context, effect, graph()->start()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 _, graph()->start()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400579 }
580 }
581}
582
583
584// -----------------------------------------------------------------------------
585// JSStoreContext
586
587
588TEST_F(JSTypedLoweringTest, JSStoreContext) {
589 Node* const context = Parameter(Type::Any());
590 Node* const effect = graph()->start();
591 Node* const control = graph()->start();
592 TRACED_FOREACH(size_t, index, kIndices) {
593 TRACED_FOREACH(Type*, type, kJSTypes) {
594 Node* const value = Parameter(type);
595
596 Reduction const r1 =
597 Reduce(graph()->NewNode(javascript()->StoreContext(0, index), context,
598 value, context, effect, control));
599 ASSERT_TRUE(r1.Changed());
600 EXPECT_THAT(r1.replacement(),
601 IsStoreField(AccessBuilder::ForContextSlot(index), context,
602 value, effect, control));
603
604 Reduction const r2 =
605 Reduce(graph()->NewNode(javascript()->StoreContext(1, index), context,
606 value, context, effect, control));
607 ASSERT_TRUE(r2.Changed());
608 EXPECT_THAT(r2.replacement(),
609 IsStoreField(AccessBuilder::ForContextSlot(index),
610 IsLoadField(AccessBuilder::ForContextSlot(
611 Context::PREVIOUS_INDEX),
612 context, effect, graph()->start()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613 value, _, control));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400614 }
615 }
616}
617
618
619// -----------------------------------------------------------------------------
620// JSLoadProperty
621
622
623TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
624 const size_t kLength = 17;
625 double backing_store[kLength];
626 Handle<JSArrayBuffer> buffer =
627 NewArrayBuffer(backing_store, sizeof(backing_store));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628 VectorSlotPair feedback;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400629 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
631 Handle<JSTypedArray> array =
632 factory()->NewJSTypedArray(type, buffer, 0, kLength);
633 int const element_size = static_cast<int>(array->element_size());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 Node* key = Parameter(
636 Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
637 Node* base = HeapConstant(array);
638 Node* vector = UndefinedConstant();
639 Node* context = UndefinedConstant();
640 Node* effect = graph()->start();
641 Node* control = graph()->start();
642 Reduction r = Reduce(
643 graph()->NewNode(javascript()->LoadProperty(language_mode, feedback),
644 base, key, vector, context, EmptyFrameState(),
645 EmptyFrameState(), effect, control));
646
647 Matcher<Node*> offset_matcher =
648 element_size == 1
649 ? key
650 : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
651
652 ASSERT_TRUE(r.Changed());
653 EXPECT_THAT(
654 r.replacement(),
655 IsLoadBuffer(BufferAccess(type),
656 IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
657 offset_matcher,
658 IsNumberConstant(array->byte_length()->Number()), effect,
659 control));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400660 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400661 }
662}
663
664
665TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) {
666 const size_t kLength = 17;
667 double backing_store[kLength];
668 Handle<JSArrayBuffer> buffer =
669 NewArrayBuffer(backing_store, sizeof(backing_store));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670 VectorSlotPair feedback;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400671 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000672 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
673 Handle<JSTypedArray> array =
674 factory()->NewJSTypedArray(type, buffer, 0, kLength);
675 ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400676
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000677 int min = random_number_generator()->NextInt(static_cast<int>(kLength));
678 int max = random_number_generator()->NextInt(static_cast<int>(kLength));
679 if (min > max) std::swap(min, max);
680 Node* key = Parameter(Type::Range(min, max, zone()));
681 Node* base = HeapConstant(array);
682 Node* vector = UndefinedConstant();
683 Node* context = UndefinedConstant();
684 Node* effect = graph()->start();
685 Node* control = graph()->start();
686 Reduction r = Reduce(
687 graph()->NewNode(javascript()->LoadProperty(language_mode, feedback),
688 base, key, vector, context, EmptyFrameState(),
689 EmptyFrameState(), effect, control));
690
691 ASSERT_TRUE(r.Changed());
692 EXPECT_THAT(
693 r.replacement(),
694 IsLoadElement(access,
695 IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
696 key, effect, control));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400697 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400698 }
699}
700
701
702// -----------------------------------------------------------------------------
703// JSStoreProperty
704
705
706TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
707 const size_t kLength = 17;
708 double backing_store[kLength];
709 Handle<JSArrayBuffer> buffer =
710 NewArrayBuffer(backing_store, sizeof(backing_store));
711 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400713 Handle<JSTypedArray> array =
714 factory()->NewJSTypedArray(type, buffer, 0, kLength);
715 int const element_size = static_cast<int>(array->element_size());
716
717 Node* key = Parameter(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400719 Node* base = HeapConstant(array);
720 Node* value =
721 Parameter(AccessBuilder::ForTypedArrayElement(type, true).type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722 Node* vector = UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400723 Node* context = UndefinedConstant();
724 Node* effect = graph()->start();
725 Node* control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000726 VectorSlotPair feedback;
727 const Operator* op = javascript()->StoreProperty(language_mode, feedback);
728 Node* node = graph()->NewNode(op, base, key, value, vector, context,
729 EmptyFrameState(), EmptyFrameState(),
730 effect, control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400731 Reduction r = Reduce(node);
732
733 Matcher<Node*> offset_matcher =
734 element_size == 1
735 ? key
736 : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
737
738 ASSERT_TRUE(r.Changed());
739 EXPECT_THAT(
740 r.replacement(),
741 IsStoreBuffer(BufferAccess(type),
742 IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
743 offset_matcher,
744 IsNumberConstant(array->byte_length()->Number()), value,
745 effect, control));
746 }
747 }
748}
749
750
751TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) {
752 const size_t kLength = 17;
753 double backing_store[kLength];
754 Handle<JSArrayBuffer> buffer =
755 NewArrayBuffer(backing_store, sizeof(backing_store));
756 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400758 Handle<JSTypedArray> array =
759 factory()->NewJSTypedArray(type, buffer, 0, kLength);
760 int const element_size = static_cast<int>(array->element_size());
761
762 Node* key = Parameter(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400764 Node* base = HeapConstant(array);
765 Node* value = Parameter(Type::Any());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 Node* vector = UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400767 Node* context = UndefinedConstant();
768 Node* effect = graph()->start();
769 Node* control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770 VectorSlotPair feedback;
771 const Operator* op = javascript()->StoreProperty(language_mode, feedback);
772 Node* node = graph()->NewNode(op, base, key, value, vector, context,
773 EmptyFrameState(), EmptyFrameState(),
774 effect, control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400775 Reduction r = Reduce(node);
776
777 Matcher<Node*> offset_matcher =
778 element_size == 1
779 ? key
780 : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
781
782 Matcher<Node*> value_matcher =
783 IsToNumber(value, context, effect, control);
784 Matcher<Node*> effect_matcher = value_matcher;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400785
786 ASSERT_TRUE(r.Changed());
787 EXPECT_THAT(
788 r.replacement(),
789 IsStoreBuffer(BufferAccess(type),
790 IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
791 offset_matcher,
792 IsNumberConstant(array->byte_length()->Number()),
793 value_matcher, effect_matcher, control));
794 }
795 }
796}
797
798
799TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) {
800 const size_t kLength = 17;
801 double backing_store[kLength];
802 Handle<JSArrayBuffer> buffer =
803 NewArrayBuffer(backing_store, sizeof(backing_store));
804 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000805 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400806 Handle<JSTypedArray> array =
807 factory()->NewJSTypedArray(type, buffer, 0, kLength);
808 ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
809
810 int min = random_number_generator()->NextInt(static_cast<int>(kLength));
811 int max = random_number_generator()->NextInt(static_cast<int>(kLength));
812 if (min > max) std::swap(min, max);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 Node* key = Parameter(Type::Range(min, max, zone()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400814 Node* base = HeapConstant(array);
815 Node* value = Parameter(access.type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 Node* vector = UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400817 Node* context = UndefinedConstant();
818 Node* effect = graph()->start();
819 Node* control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000820 VectorSlotPair feedback;
821 const Operator* op = javascript()->StoreProperty(language_mode, feedback);
822 Node* node = graph()->NewNode(op, base, key, value, vector, context,
823 EmptyFrameState(), EmptyFrameState(),
824 effect, control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400825 Reduction r = Reduce(node);
826
827 ASSERT_TRUE(r.Changed());
828 EXPECT_THAT(
829 r.replacement(),
830 IsStoreElement(
831 access, IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
832 key, value, effect, control));
833 }
834 }
835}
836
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837
838// -----------------------------------------------------------------------------
839// JSLoadNamed
840
841
842TEST_F(JSTypedLoweringTest, JSLoadNamedStringLength) {
843 VectorSlotPair feedback;
844 Handle<Name> name = factory()->length_string();
845 Node* const receiver = Parameter(Type::String(), 0);
846 Node* const vector = Parameter(Type::Internal(), 1);
847 Node* const context = UndefinedConstant();
848 Node* const effect = graph()->start();
849 Node* const control = graph()->start();
850 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
851 Reduction const r = Reduce(
852 graph()->NewNode(javascript()->LoadNamed(language_mode, name, feedback),
853 receiver, vector, context, EmptyFrameState(),
854 EmptyFrameState(), effect, control));
855 ASSERT_TRUE(r.Changed());
856 EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
857 receiver, effect, control));
858 }
859}
860
861
862TEST_F(JSTypedLoweringTest, JSLoadNamedFunctionPrototype) {
863 VectorSlotPair feedback;
864 Handle<Name> name = factory()->prototype_string();
865 Handle<JSFunction> function = isolate()->object_function();
866 Handle<JSObject> function_prototype(JSObject::cast(function->prototype()));
867 Node* const receiver = Parameter(Type::Constant(function, zone()), 0);
868 Node* const vector = Parameter(Type::Internal(), 1);
869 Node* const context = Parameter(Type::Internal(), 2);
870 Node* const effect = graph()->start();
871 Node* const control = graph()->start();
872 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
873 Reduction const r = Reduce(
874 graph()->NewNode(javascript()->LoadNamed(language_mode, name, feedback),
875 receiver, vector, context, EmptyFrameState(),
876 EmptyFrameState(), effect, control));
877 ASSERT_TRUE(r.Changed());
878 EXPECT_THAT(r.replacement(), IsHeapConstant(function_prototype));
879 }
880}
881
882
883// -----------------------------------------------------------------------------
884// JSAdd
885
886
887TEST_F(JSTypedLoweringTest, JSAddWithString) {
888 BinaryOperationHints const hints = BinaryOperationHints::Any();
889 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
890 Node* lhs = Parameter(Type::String(), 0);
891 Node* rhs = Parameter(Type::String(), 1);
892 Node* context = Parameter(Type::Any(), 2);
893 Node* frame_state0 = EmptyFrameState();
894 Node* frame_state1 = EmptyFrameState();
895 Node* effect = graph()->start();
896 Node* control = graph()->start();
897 Reduction r = Reduce(
898 graph()->NewNode(javascript()->Add(language_mode, hints), lhs, rhs,
899 context, frame_state0, frame_state1, effect, control));
900 ASSERT_TRUE(r.Changed());
901 EXPECT_THAT(r.replacement(),
902 IsCall(_, IsHeapConstant(CodeFactory::StringAdd(
903 isolate(), STRING_ADD_CHECK_NONE,
904 NOT_TENURED).code()),
905 lhs, rhs, context, frame_state0, effect, control));
906 }
907}
908
909
910// -----------------------------------------------------------------------------
911// JSCreate
912
913
914TEST_F(JSTypedLoweringTest, JSCreate) {
915 Handle<JSFunction> function = isolate()->object_function();
916 Node* const target = Parameter(Type::Constant(function, graph()->zone()));
917 Node* const context = Parameter(Type::Any());
918 Node* const effect = graph()->start();
919 Reduction r = Reduce(graph()->NewNode(javascript()->Create(), target, target,
920 context, EmptyFrameState(), effect));
921 ASSERT_TRUE(r.Changed());
922 EXPECT_THAT(
923 r.replacement(),
924 IsFinishRegion(
925 IsAllocate(IsNumberConstant(function->initial_map()->instance_size()),
926 IsBeginRegion(effect), _),
927 _));
928}
929
930
931// -----------------------------------------------------------------------------
932// JSCreateArguments
933
934
935TEST_F(JSTypedLoweringTest, JSCreateArgumentsViaStub) {
936 Node* const closure = Parameter(Type::Any());
937 Node* const context = UndefinedConstant();
938 Node* const effect = graph()->start();
939 Node* const control = graph()->start();
940 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
941 Node* const frame_state = FrameState(shared, graph()->start());
942 Reduction r = Reduce(
943 graph()->NewNode(javascript()->CreateArguments(
944 CreateArgumentsParameters::kMappedArguments, 0),
945 closure, context, frame_state, effect, control));
946 ASSERT_TRUE(r.Changed());
947 EXPECT_THAT(r.replacement(),
948 IsCall(_, IsHeapConstant(CodeFactory::ArgumentsAccess(
949 isolate(), false, false)
950 .code()),
951 closure, IsNumberConstant(0), _, effect, control));
952}
953
954
955TEST_F(JSTypedLoweringTest, JSCreateArgumentsRestArrayViaStub) {
956 Node* const closure = Parameter(Type::Any());
957 Node* const context = UndefinedConstant();
958 Node* const effect = graph()->start();
959 Node* const control = graph()->start();
960 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
961 Node* const frame_state = FrameState(shared, graph()->start());
962 Reduction r = Reduce(graph()->NewNode(
963 javascript()->CreateArguments(CreateArgumentsParameters::kRestArray, 0),
964 closure, context, frame_state, effect, control));
965 ASSERT_TRUE(r.Changed());
966 EXPECT_THAT(
967 r.replacement(),
968 IsCall(_,
969 IsHeapConstant(CodeFactory::RestArgumentsAccess(isolate()).code()),
970 IsNumberConstant(0), _, IsNumberConstant(0), _, effect, control));
971}
972
973
974TEST_F(JSTypedLoweringTest, JSCreateArgumentsInlinedMapped) {
975 Node* const closure = Parameter(Type::Any());
976 Node* const context = UndefinedConstant();
977 Node* const effect = graph()->start();
978 Node* const control = graph()->start();
979 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
980 Node* const frame_state_outer = FrameState(shared, graph()->start());
981 Node* const frame_state_inner = FrameState(shared, frame_state_outer);
982 Reduction r = Reduce(
983 graph()->NewNode(javascript()->CreateArguments(
984 CreateArgumentsParameters::kMappedArguments, 0),
985 closure, context, frame_state_inner, effect, control));
986 ASSERT_TRUE(r.Changed());
987 EXPECT_THAT(r.replacement(),
988 IsFinishRegion(
989 IsAllocate(IsNumberConstant(Heap::kSloppyArgumentsObjectSize),
990 _, control),
991 _));
992}
993
994
995TEST_F(JSTypedLoweringTest, JSCreateArgumentsInlinedUnmapped) {
996 Node* const closure = Parameter(Type::Any());
997 Node* const context = UndefinedConstant();
998 Node* const effect = graph()->start();
999 Node* const control = graph()->start();
1000 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
1001 Node* const frame_state_outer = FrameState(shared, graph()->start());
1002 Node* const frame_state_inner = FrameState(shared, frame_state_outer);
1003 Reduction r = Reduce(
1004 graph()->NewNode(javascript()->CreateArguments(
1005 CreateArgumentsParameters::kUnmappedArguments, 0),
1006 closure, context, frame_state_inner, effect, control));
1007 ASSERT_TRUE(r.Changed());
1008 EXPECT_THAT(r.replacement(),
1009 IsFinishRegion(
1010 IsAllocate(IsNumberConstant(Heap::kStrictArgumentsObjectSize),
1011 _, control),
1012 _));
1013}
1014
1015
1016TEST_F(JSTypedLoweringTest, JSCreateArgumentsInlinedRestArray) {
1017 Node* const closure = Parameter(Type::Any());
1018 Node* const context = UndefinedConstant();
1019 Node* const effect = graph()->start();
1020 Node* const control = graph()->start();
1021 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
1022 Node* const frame_state_outer = FrameState(shared, graph()->start());
1023 Node* const frame_state_inner = FrameState(shared, frame_state_outer);
1024 Reduction r = Reduce(graph()->NewNode(
1025 javascript()->CreateArguments(CreateArgumentsParameters::kRestArray, 0),
1026 closure, context, frame_state_inner, effect, control));
1027 ASSERT_TRUE(r.Changed());
1028 EXPECT_THAT(r.replacement(),
1029 IsFinishRegion(
1030 IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
1031}
1032
1033
1034// -----------------------------------------------------------------------------
1035// JSCreateClosure
1036
1037
1038TEST_F(JSTypedLoweringTest, JSCreateClosure) {
1039 Node* const context = UndefinedConstant();
1040 Node* const effect = graph()->start();
1041 Node* const control = graph()->start();
1042 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
1043 Reduction r =
1044 Reduce(graph()->NewNode(javascript()->CreateClosure(shared, NOT_TENURED),
1045 context, effect, control));
1046 ASSERT_TRUE(r.Changed());
1047 EXPECT_THAT(r.replacement(),
1048 IsCall(_, IsHeapConstant(CodeFactory::FastNewClosure(
1049 isolate(), shared->language_mode(),
1050 shared->kind()).code()),
1051 IsHeapConstant(shared), effect, control));
1052}
1053
1054
1055// -----------------------------------------------------------------------------
1056// JSCreateLiteralArray
1057
1058
1059TEST_F(JSTypedLoweringTest, JSCreateLiteralArray) {
1060 Handle<FixedArray> const constant_elements = factory()->NewFixedArray(12);
1061 int const literal_flags = ArrayLiteral::kShallowElements;
1062 int const literal_index = 1;
1063 Node* const closure = Parameter(0);
1064 Node* const context = Parameter(1);
1065 Node* const frame_state = EmptyFrameState();
1066 Node* const effect = graph()->start();
1067 Node* const control = graph()->start();
1068 Reduction const r = Reduce(
1069 graph()->NewNode(javascript()->CreateLiteralArray(
1070 constant_elements, literal_flags, literal_index),
1071 closure, context, frame_state, effect, control));
1072 ASSERT_TRUE(r.Changed());
1073 EXPECT_THAT(
1074 r.replacement(),
1075 IsCall(_, IsHeapConstant(
1076 CodeFactory::FastCloneShallowArray(isolate()).code()),
1077 closure, IsNumberConstant(literal_index),
1078 IsHeapConstant(constant_elements), context, frame_state, effect,
1079 control));
1080}
1081
1082
1083// -----------------------------------------------------------------------------
1084// JSCreateLiteralObject
1085
1086
1087TEST_F(JSTypedLoweringTest, JSCreateLiteralObject) {
1088 Handle<FixedArray> const constant_properties =
1089 factory()->NewFixedArray(6 * 2);
1090 int const literal_flags = ObjectLiteral::kShallowProperties;
1091 int const literal_index = 1;
1092 Node* const closure = Parameter(0);
1093 Node* const context = Parameter(1);
1094 Node* const frame_state = EmptyFrameState();
1095 Node* const effect = graph()->start();
1096 Node* const control = graph()->start();
1097 Reduction const r = Reduce(
1098 graph()->NewNode(javascript()->CreateLiteralObject(
1099 constant_properties, literal_flags, literal_index),
1100 closure, context, frame_state, effect, control));
1101 ASSERT_TRUE(r.Changed());
1102 EXPECT_THAT(
1103 r.replacement(),
1104 IsCall(_, IsHeapConstant(
1105 CodeFactory::FastCloneShallowObject(isolate(), 6).code()),
1106 closure, IsNumberConstant(literal_index),
1107 IsHeapConstant(constant_properties), _, context, frame_state,
1108 effect, control));
1109}
1110
1111
1112// -----------------------------------------------------------------------------
1113// JSCreateFunctionContext
1114
1115
1116TEST_F(JSTypedLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
1117 Node* const closure = Parameter(Type::Any());
1118 Node* const context = Parameter(Type::Any());
1119 Node* const effect = graph()->start();
1120 Node* const control = graph()->start();
1121 Reduction const r =
1122 Reduce(graph()->NewNode(javascript()->CreateFunctionContext(8), closure,
1123 context, effect, control));
1124 ASSERT_TRUE(r.Changed());
1125 EXPECT_THAT(r.replacement(),
1126 IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
1127 8 + Context::MIN_CONTEXT_SLOTS)),
1128 IsBeginRegion(_), control),
1129 _));
1130}
1131
1132
1133TEST_F(JSTypedLoweringTest, JSCreateFunctionContextViaStub) {
1134 Node* const closure = Parameter(Type::Any());
1135 Node* const context = Parameter(Type::Any());
1136 Node* const effect = graph()->start();
1137 Node* const control = graph()->start();
1138 Reduction const r =
1139 Reduce(graph()->NewNode(javascript()->CreateFunctionContext(32), closure,
1140 context, effect, control));
1141 ASSERT_TRUE(r.Changed());
1142 EXPECT_THAT(r.replacement(),
1143 IsCall(_, IsHeapConstant(
1144 CodeFactory::FastNewContext(isolate(), 32).code()),
1145 closure, context, effect, control));
1146}
1147
1148
1149// -----------------------------------------------------------------------------
1150// JSCreateWithContext
1151
1152
1153TEST_F(JSTypedLoweringTest, JSCreateWithContext) {
1154 Node* const object = Parameter(Type::Receiver());
1155 Node* const closure = Parameter(Type::Function());
1156 Node* const context = Parameter(Type::Any());
1157 Node* const effect = graph()->start();
1158 Node* const control = graph()->start();
1159 Reduction r =
1160 Reduce(graph()->NewNode(javascript()->CreateWithContext(), object,
1161 closure, context, effect, control));
1162 ASSERT_TRUE(r.Changed());
1163 EXPECT_THAT(r.replacement(),
1164 IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
1165 Context::MIN_CONTEXT_SLOTS)),
1166 IsBeginRegion(_), control),
1167 _));
1168}
1169
1170
1171// -----------------------------------------------------------------------------
1172// JSCreateCatchContext
1173
1174
1175TEST_F(JSTypedLoweringTest, JSCreateCatchContext) {
1176 Handle<String> name = factory()->length_string();
1177 Node* const exception = Parameter(Type::Receiver());
1178 Node* const closure = Parameter(Type::Function());
1179 Node* const context = Parameter(Type::Any());
1180 Node* const effect = graph()->start();
1181 Node* const control = graph()->start();
1182 Reduction r =
1183 Reduce(graph()->NewNode(javascript()->CreateCatchContext(name), exception,
1184 closure, context, effect, control));
1185 ASSERT_TRUE(r.Changed());
1186 EXPECT_THAT(r.replacement(),
1187 IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
1188 Context::MIN_CONTEXT_SLOTS + 1)),
1189 IsBeginRegion(_), control),
1190 _));
1191}
1192
1193
1194// -----------------------------------------------------------------------------
1195// JSInstanceOf
1196// Test that instanceOf is reduced if and only if the right-hand side is a
1197// function constant. Functional correctness is ensured elsewhere.
1198
1199
1200TEST_F(JSTypedLoweringTest, JSInstanceOfSpecializationWithoutSmiCheck) {
1201 Node* const context = Parameter(Type::Any());
1202 Node* const frame_state = EmptyFrameState();
1203 Node* const effect = graph()->start();
1204 Node* const control = graph()->start();
1205
1206 // Reduce if left-hand side is known to be an object.
1207 Node* instanceOf =
1208 graph()->NewNode(javascript()->InstanceOf(), Parameter(Type::Object(), 0),
1209 HeapConstant(isolate()->object_function()), context,
1210 frame_state, effect, control);
1211 Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
1212 frame_state, effect, control);
1213 Reduction r = Reduce(instanceOf);
1214 ASSERT_TRUE(r.Changed());
1215 ASSERT_EQ(r.replacement(), dummy->InputAt(0));
1216 ASSERT_NE(instanceOf, dummy->InputAt(0));
1217}
1218
1219
1220TEST_F(JSTypedLoweringTest, JSInstanceOfSpecializationWithSmiCheck) {
1221 Node* const context = Parameter(Type::Any());
1222 Node* const frame_state = EmptyFrameState();
1223 Node* const effect = graph()->start();
1224 Node* const control = graph()->start();
1225
1226 // Reduce if left-hand side could be a Smi.
1227 Node* instanceOf =
1228 graph()->NewNode(javascript()->InstanceOf(), Parameter(Type::Any(), 0),
1229 HeapConstant(isolate()->object_function()), context,
1230 frame_state, effect, control);
1231 Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
1232 frame_state, effect, control);
1233 Reduction r = Reduce(instanceOf);
1234 ASSERT_TRUE(r.Changed());
1235 ASSERT_EQ(r.replacement(), dummy->InputAt(0));
1236 ASSERT_NE(instanceOf, dummy->InputAt(0));
1237}
1238
1239
1240TEST_F(JSTypedLoweringTest, JSInstanceOfNoSpecialization) {
1241 Node* const context = Parameter(Type::Any());
1242 Node* const frame_state = EmptyFrameState();
1243 Node* const effect = graph()->start();
1244 Node* const control = graph()->start();
1245
1246 // Do not reduce if right-hand side is not a function constant.
1247 Node* instanceOf = graph()->NewNode(
1248 javascript()->InstanceOf(), Parameter(Type::Any(), 0),
1249 Parameter(Type::Any()), context, frame_state, effect, control);
1250 Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
1251 frame_state, effect, control);
1252 Reduction r = Reduce(instanceOf);
1253 ASSERT_FALSE(r.Changed());
1254 ASSERT_EQ(instanceOf, dummy->InputAt(0));
1255}
1256
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001257} // namespace compiler
1258} // namespace internal
1259} // namespace v8