blob: 3a8e778dc045830cd6288c47569ccf8188967df2 [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);
Ben Murdochda12d292016-06-02 14:46:10 +010070const LanguageMode kLanguageModes[] = {SLOPPY, STRICT};
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_,
Ben Murdoch61f157c2016-09-16 13:49:30 +010090 JSTypedLowering::kDeoptimizationEnabled |
91 JSTypedLowering::kTypeFeedbackEnabled,
92 &jsgraph, zone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040093 return reducer.Reduce(node);
94 }
95
96 Handle<JSArrayBuffer> NewArrayBuffer(void* bytes, size_t byte_length) {
97 Handle<JSArrayBuffer> buffer = factory()->NewJSArrayBuffer();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 JSArrayBuffer::Setup(buffer, isolate(), true, bytes, byte_length);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040099 return buffer;
100 }
101
102 Matcher<Node*> IsIntPtrConstant(intptr_t value) {
103 return sizeof(value) == 4 ? IsInt32Constant(static_cast<int32_t>(value))
104 : IsInt64Constant(static_cast<int64_t>(value));
105 }
106
107 JSOperatorBuilder* javascript() { return &javascript_; }
108
109 private:
110 JSOperatorBuilder javascript_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 CompilationDependencies deps_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400112};
113
114
115// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400116// Constant propagation
117
118
119TEST_F(JSTypedLoweringTest, ParameterWithMinusZero) {
120 {
121 Reduction r = Reduce(
122 Parameter(Type::Constant(factory()->minus_zero_value(), zone())));
123 ASSERT_TRUE(r.Changed());
124 EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
125 }
126 {
127 Reduction r = Reduce(Parameter(Type::MinusZero()));
128 ASSERT_TRUE(r.Changed());
129 EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
130 }
131 {
132 Reduction r = Reduce(Parameter(
133 Type::Union(Type::MinusZero(),
134 Type::Constant(factory()->NewNumber(0), zone()), zone())));
135 EXPECT_FALSE(r.Changed());
136 }
137}
138
139
140TEST_F(JSTypedLoweringTest, ParameterWithNull) {
141 Handle<HeapObject> null = factory()->null_value();
142 {
143 Reduction r = Reduce(Parameter(Type::Constant(null, zone())));
144 ASSERT_TRUE(r.Changed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 EXPECT_THAT(r.replacement(), IsHeapConstant(null));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400146 }
147 {
148 Reduction r = Reduce(Parameter(Type::Null()));
149 ASSERT_TRUE(r.Changed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 EXPECT_THAT(r.replacement(), IsHeapConstant(null));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400151 }
152}
153
154
155TEST_F(JSTypedLoweringTest, ParameterWithNaN) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400157 std::numeric_limits<double>::quiet_NaN(),
158 std::numeric_limits<double>::signaling_NaN()};
159 TRACED_FOREACH(double, nan, kNaNs) {
160 Handle<Object> constant = factory()->NewNumber(nan);
161 Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
162 ASSERT_TRUE(r.Changed());
163 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
164 }
165 {
166 Reduction r =
167 Reduce(Parameter(Type::Constant(factory()->nan_value(), zone())));
168 ASSERT_TRUE(r.Changed());
169 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
170 }
171 {
172 Reduction r = Reduce(Parameter(Type::NaN()));
173 ASSERT_TRUE(r.Changed());
174 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
175 }
176}
177
178
179TEST_F(JSTypedLoweringTest, ParameterWithPlainNumber) {
180 TRACED_FOREACH(double, value, kFloat64Values) {
181 Handle<Object> constant = factory()->NewNumber(value);
182 Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
183 ASSERT_TRUE(r.Changed());
184 EXPECT_THAT(r.replacement(), IsNumberConstant(value));
185 }
186 TRACED_FOREACH(double, value, kIntegerValues) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 Reduction r = Reduce(Parameter(Type::Range(value, value, zone())));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400188 ASSERT_TRUE(r.Changed());
189 EXPECT_THAT(r.replacement(), IsNumberConstant(value));
190 }
191}
192
193
194TEST_F(JSTypedLoweringTest, ParameterWithUndefined) {
195 Handle<HeapObject> undefined = factory()->undefined_value();
196 {
197 Reduction r = Reduce(Parameter(Type::Undefined()));
198 ASSERT_TRUE(r.Changed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400200 }
201 {
202 Reduction r = Reduce(Parameter(Type::Constant(undefined, zone())));
203 ASSERT_TRUE(r.Changed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400205 }
206}
207
208
209// -----------------------------------------------------------------------------
210// JSToBoolean
211
212
213TEST_F(JSTypedLoweringTest, JSToBooleanWithBoolean) {
214 Node* input = Parameter(Type::Boolean(), 0);
215 Node* context = Parameter(Type::Any(), 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100216 Reduction r = Reduce(graph()->NewNode(
217 javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400218 ASSERT_TRUE(r.Changed());
219 EXPECT_EQ(input, r.replacement());
220}
221
222
223TEST_F(JSTypedLoweringTest, JSToBooleanWithFalsish) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400224 Node* input = Parameter(
225 Type::Union(
226 Type::MinusZero(),
227 Type::Union(
228 Type::NaN(),
229 Type::Union(
230 Type::Null(),
231 Type::Union(
232 Type::Undefined(),
233 Type::Union(
234 Type::Undetectable(),
235 Type::Union(
236 Type::Constant(factory()->false_value(), zone()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 Type::Range(0.0, 0.0, zone()), zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400238 zone()),
239 zone()),
240 zone()),
241 zone()),
242 zone()),
243 0);
244 Node* context = Parameter(Type::Any(), 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100245 Reduction r = Reduce(graph()->NewNode(
246 javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400247 ASSERT_TRUE(r.Changed());
248 EXPECT_THAT(r.replacement(), IsFalseConstant());
249}
250
251
252TEST_F(JSTypedLoweringTest, JSToBooleanWithTruish) {
253 Node* input = Parameter(
254 Type::Union(
255 Type::Constant(factory()->true_value(), zone()),
256 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
257 zone()),
258 0);
259 Node* context = Parameter(Type::Any(), 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100260 Reduction r = Reduce(graph()->NewNode(
261 javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400262 ASSERT_TRUE(r.Changed());
263 EXPECT_THAT(r.replacement(), IsTrueConstant());
264}
265
266
267TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400269 Node* context = Parameter(Type::Any(), 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100270 Reduction r = Reduce(graph()->NewNode(
271 javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400272 ASSERT_TRUE(r.Changed());
273 EXPECT_THAT(r.replacement(), IsTrueConstant());
274}
275
276
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) {
278 Node* input = Parameter(Type::OrderedNumber(), 0);
279 Node* context = Parameter(Type::Any(), 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100280 Reduction r = Reduce(graph()->NewNode(
281 javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 ASSERT_TRUE(r.Changed());
283 EXPECT_THAT(r.replacement(),
284 IsBooleanNot(IsNumberEqual(input, IsNumberConstant(0.0))));
285}
286
287
288TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
289 Node* input = Parameter(Type::String(), 0);
290 Node* context = Parameter(Type::Any(), 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100291 Reduction r = Reduce(graph()->NewNode(
292 javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 ASSERT_TRUE(r.Changed());
294 EXPECT_THAT(
295 r.replacement(),
296 IsNumberLessThan(IsNumberConstant(0.0),
297 IsLoadField(AccessBuilder::ForStringLength(), input,
298 graph()->start(), graph()->start())));
299}
300
301
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400302TEST_F(JSTypedLoweringTest, JSToBooleanWithAny) {
303 Node* input = Parameter(Type::Any(), 0);
304 Node* context = Parameter(Type::Any(), 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100305 Reduction r = Reduce(graph()->NewNode(
306 javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307 ASSERT_FALSE(r.Changed());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400308}
309
310
311// -----------------------------------------------------------------------------
312// JSToNumber
313
314
315TEST_F(JSTypedLoweringTest, JSToNumberWithPlainPrimitive) {
316 Node* const input = Parameter(Type::PlainPrimitive(), 0);
317 Node* const context = Parameter(Type::Any(), 1);
318 Node* const effect = graph()->start();
319 Node* const control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 Reduction r =
321 Reduce(graph()->NewNode(javascript()->ToNumber(), input, context,
322 EmptyFrameState(), effect, control));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400323 ASSERT_TRUE(r.Changed());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100324 EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400325}
326
327
328// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329// JSToObject
330
331
332TEST_F(JSTypedLoweringTest, JSToObjectWithAny) {
333 Node* const input = Parameter(Type::Any(), 0);
334 Node* const context = Parameter(Type::Any(), 1);
335 Node* const frame_state = EmptyFrameState();
336 Node* const effect = graph()->start();
337 Node* const control = graph()->start();
338 Reduction r = Reduce(graph()->NewNode(javascript()->ToObject(), input,
339 context, frame_state, effect, control));
340 ASSERT_TRUE(r.Changed());
341 EXPECT_THAT(r.replacement(), IsPhi(MachineRepresentation::kTagged, _, _, _));
342}
343
344
345TEST_F(JSTypedLoweringTest, JSToObjectWithReceiver) {
346 Node* const input = Parameter(Type::Receiver(), 0);
347 Node* const context = Parameter(Type::Any(), 1);
348 Node* const frame_state = EmptyFrameState();
349 Node* const effect = graph()->start();
350 Node* const control = graph()->start();
351 Reduction r = Reduce(graph()->NewNode(javascript()->ToObject(), input,
352 context, frame_state, effect, control));
353 ASSERT_TRUE(r.Changed());
354 EXPECT_EQ(input, r.replacement());
355}
356
357
358// -----------------------------------------------------------------------------
359// JSToString
360
361
362TEST_F(JSTypedLoweringTest, JSToStringWithBoolean) {
363 Node* const input = Parameter(Type::Boolean(), 0);
364 Node* const context = Parameter(Type::Any(), 1);
365 Node* const frame_state = EmptyFrameState();
366 Node* const effect = graph()->start();
367 Node* const control = graph()->start();
368 Reduction r = Reduce(graph()->NewNode(javascript()->ToString(), input,
369 context, frame_state, effect, control));
370 ASSERT_TRUE(r.Changed());
371 EXPECT_THAT(r.replacement(),
372 IsSelect(MachineRepresentation::kTagged, input,
373 IsHeapConstant(factory()->true_string()),
374 IsHeapConstant(factory()->false_string())));
375}
376
377
378// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400379// JSStrictEqual
380
381
382TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) {
383 Node* const the_hole = HeapConstant(factory()->the_hole_value());
384 Node* const context = UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400385 TRACED_FOREACH(Type*, type, kJSTypes) {
386 Node* const lhs = Parameter(type);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100387 Reduction r = Reduce(graph()->NewNode(
388 javascript()->StrictEqual(CompareOperationHints::Any()), lhs, the_hole,
389 context));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400390 ASSERT_TRUE(r.Changed());
391 EXPECT_THAT(r.replacement(), IsFalseConstant());
392 }
393}
394
395
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) {
397 Node* const lhs = Parameter(Type::Unique(), 0);
398 Node* const rhs = Parameter(Type::Unique(), 1);
399 Node* const context = Parameter(Type::Any(), 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100400 Reduction r = Reduce(
401 graph()->NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
402 lhs, rhs, context));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000403 ASSERT_TRUE(r.Changed());
404 EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs));
405}
406
407
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400408// -----------------------------------------------------------------------------
409// JSShiftLeft
410
411
412TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400414 Node* const lhs = Parameter(Type::Signed32());
415 Node* const context = UndefinedConstant();
416 Node* const effect = graph()->start();
417 Node* const control = graph()->start();
418 TRACED_FORRANGE(double, rhs, 0, 31) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100419 Reduction r = Reduce(graph()->NewNode(
420 javascript()->ShiftLeft(hints), lhs, NumberConstant(rhs), context,
421 EmptyFrameState(), EmptyFrameState(), effect, control));
422 ASSERT_TRUE(r.Changed());
423 EXPECT_THAT(r.replacement(),
424 IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400425 }
426}
427
428
429TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400431 Node* const lhs = Parameter(Type::Signed32());
432 Node* const rhs = Parameter(Type::Unsigned32());
433 Node* const context = UndefinedConstant();
434 Node* const effect = graph()->start();
435 Node* const control = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100436 Reduction r = Reduce(graph()->NewNode(javascript()->ShiftLeft(hints), lhs,
437 rhs, context, EmptyFrameState(),
438 EmptyFrameState(), effect, control));
439 ASSERT_TRUE(r.Changed());
440 EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400441}
442
443
444// -----------------------------------------------------------------------------
445// JSShiftRight
446
447
448TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000449 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400450 Node* const lhs = Parameter(Type::Signed32());
451 Node* const context = UndefinedConstant();
452 Node* const effect = graph()->start();
453 Node* const control = graph()->start();
454 TRACED_FORRANGE(double, rhs, 0, 31) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100455 Reduction r = Reduce(graph()->NewNode(
456 javascript()->ShiftRight(hints), lhs, NumberConstant(rhs), context,
457 EmptyFrameState(), EmptyFrameState(), effect, control));
458 ASSERT_TRUE(r.Changed());
459 EXPECT_THAT(r.replacement(),
460 IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400461 }
462}
463
464
465TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400467 Node* const lhs = Parameter(Type::Signed32());
468 Node* const rhs = Parameter(Type::Unsigned32());
469 Node* const context = UndefinedConstant();
470 Node* const effect = graph()->start();
471 Node* const control = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100472 Reduction r = Reduce(graph()->NewNode(javascript()->ShiftRight(hints), lhs,
473 rhs, context, EmptyFrameState(),
474 EmptyFrameState(), effect, control));
475 ASSERT_TRUE(r.Changed());
476 EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400477}
478
479
480// -----------------------------------------------------------------------------
481// JSShiftRightLogical
482
483
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484TEST_F(JSTypedLoweringTest,
485 JSShiftRightLogicalWithUnsigned32AndConstant) {
486 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400487 Node* const lhs = Parameter(Type::Unsigned32());
488 Node* const context = UndefinedConstant();
489 Node* const effect = graph()->start();
490 Node* const control = graph()->start();
491 TRACED_FORRANGE(double, rhs, 0, 31) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100492 Reduction r = Reduce(graph()->NewNode(
493 javascript()->ShiftRightLogical(hints), lhs, NumberConstant(rhs),
494 context, EmptyFrameState(), EmptyFrameState(), effect, control));
495 ASSERT_TRUE(r.Changed());
496 EXPECT_THAT(r.replacement(),
497 IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400498 }
499}
500
501
502TEST_F(JSTypedLoweringTest, JSShiftRightLogicalWithUnsigned32AndUnsigned32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 BinaryOperationHints const hints = BinaryOperationHints::Any();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400504 Node* const lhs = Parameter(Type::Unsigned32());
505 Node* const rhs = Parameter(Type::Unsigned32());
506 Node* const context = UndefinedConstant();
507 Node* const effect = graph()->start();
508 Node* const control = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100509 Reduction r = Reduce(graph()->NewNode(javascript()->ShiftRightLogical(hints),
510 lhs, rhs, context, EmptyFrameState(),
511 EmptyFrameState(), effect, control));
512 ASSERT_TRUE(r.Changed());
513 EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400514}
515
516
517// -----------------------------------------------------------------------------
518// JSLoadContext
519
520
521TEST_F(JSTypedLoweringTest, JSLoadContext) {
522 Node* const context = Parameter(Type::Any());
523 Node* const effect = graph()->start();
524 static bool kBooleans[] = {false, true};
525 TRACED_FOREACH(size_t, index, kIndices) {
526 TRACED_FOREACH(bool, immutable, kBooleans) {
527 Reduction const r1 = Reduce(
528 graph()->NewNode(javascript()->LoadContext(0, index, immutable),
529 context, context, effect));
530 ASSERT_TRUE(r1.Changed());
531 EXPECT_THAT(r1.replacement(),
532 IsLoadField(AccessBuilder::ForContextSlot(index), context,
533 effect, graph()->start()));
534
535 Reduction const r2 = Reduce(
536 graph()->NewNode(javascript()->LoadContext(1, index, immutable),
537 context, context, effect));
538 ASSERT_TRUE(r2.Changed());
539 EXPECT_THAT(r2.replacement(),
540 IsLoadField(AccessBuilder::ForContextSlot(index),
541 IsLoadField(AccessBuilder::ForContextSlot(
542 Context::PREVIOUS_INDEX),
543 context, effect, graph()->start()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 _, graph()->start()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400545 }
546 }
547}
548
549
550// -----------------------------------------------------------------------------
551// JSStoreContext
552
553
554TEST_F(JSTypedLoweringTest, JSStoreContext) {
555 Node* const context = Parameter(Type::Any());
556 Node* const effect = graph()->start();
557 Node* const control = graph()->start();
558 TRACED_FOREACH(size_t, index, kIndices) {
559 TRACED_FOREACH(Type*, type, kJSTypes) {
560 Node* const value = Parameter(type);
561
562 Reduction const r1 =
563 Reduce(graph()->NewNode(javascript()->StoreContext(0, index), context,
564 value, context, effect, control));
565 ASSERT_TRUE(r1.Changed());
566 EXPECT_THAT(r1.replacement(),
567 IsStoreField(AccessBuilder::ForContextSlot(index), context,
568 value, effect, control));
569
570 Reduction const r2 =
571 Reduce(graph()->NewNode(javascript()->StoreContext(1, index), context,
572 value, context, effect, control));
573 ASSERT_TRUE(r2.Changed());
574 EXPECT_THAT(r2.replacement(),
575 IsStoreField(AccessBuilder::ForContextSlot(index),
576 IsLoadField(AccessBuilder::ForContextSlot(
577 Context::PREVIOUS_INDEX),
578 context, effect, graph()->start()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 value, _, control));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400580 }
581 }
582}
583
584
585// -----------------------------------------------------------------------------
586// JSLoadProperty
587
588
589TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
590 const size_t kLength = 17;
591 double backing_store[kLength];
592 Handle<JSArrayBuffer> buffer =
593 NewArrayBuffer(backing_store, sizeof(backing_store));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 VectorSlotPair feedback;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400595 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100596 Handle<JSTypedArray> array =
597 factory()->NewJSTypedArray(type, buffer, 0, kLength);
598 int const element_size = static_cast<int>(array->element_size());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400599
Ben Murdoch097c5b22016-05-18 11:27:45 +0100600 Node* key = Parameter(
601 Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
602 Node* base = HeapConstant(array);
603 Node* vector = UndefinedConstant();
604 Node* context = UndefinedConstant();
605 Node* effect = graph()->start();
606 Node* control = graph()->start();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100607 Reduction r = Reduce(graph()->NewNode(javascript()->LoadProperty(feedback),
608 base, key, vector, context,
609 EmptyFrameState(), effect, control));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610
Ben Murdoch097c5b22016-05-18 11:27:45 +0100611 Matcher<Node*> offset_matcher =
612 element_size == 1
613 ? key
614 : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615
Ben Murdoch097c5b22016-05-18 11:27:45 +0100616 ASSERT_TRUE(r.Changed());
617 EXPECT_THAT(
618 r.replacement(),
619 IsLoadBuffer(BufferAccess(type),
620 IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
621 offset_matcher,
622 IsNumberConstant(array->byte_length()->Number()), effect,
623 control));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400624 }
625}
626
627
628TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) {
629 const size_t kLength = 17;
630 double backing_store[kLength];
631 Handle<JSArrayBuffer> buffer =
632 NewArrayBuffer(backing_store, sizeof(backing_store));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 VectorSlotPair feedback;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400634 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100635 Handle<JSTypedArray> array =
636 factory()->NewJSTypedArray(type, buffer, 0, kLength);
637 ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400638
Ben Murdoch097c5b22016-05-18 11:27:45 +0100639 int min = random_number_generator()->NextInt(static_cast<int>(kLength));
640 int max = random_number_generator()->NextInt(static_cast<int>(kLength));
641 if (min > max) std::swap(min, max);
642 Node* key = Parameter(Type::Range(min, max, zone()));
643 Node* base = HeapConstant(array);
644 Node* vector = UndefinedConstant();
645 Node* context = UndefinedConstant();
646 Node* effect = graph()->start();
647 Node* control = graph()->start();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100648 Reduction r = Reduce(graph()->NewNode(javascript()->LoadProperty(feedback),
649 base, key, vector, context,
650 EmptyFrameState(), effect, control));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000651
Ben Murdoch097c5b22016-05-18 11:27:45 +0100652 ASSERT_TRUE(r.Changed());
653 EXPECT_THAT(
654 r.replacement(),
655 IsLoadElement(access,
656 IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
657 key, effect, control));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400658 }
659}
660
661
662// -----------------------------------------------------------------------------
663// JSStoreProperty
664
665
666TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
667 const size_t kLength = 17;
668 double backing_store[kLength];
669 Handle<JSArrayBuffer> buffer =
670 NewArrayBuffer(backing_store, sizeof(backing_store));
671 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000672 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400673 Handle<JSTypedArray> array =
674 factory()->NewJSTypedArray(type, buffer, 0, kLength);
675 int const element_size = static_cast<int>(array->element_size());
676
677 Node* key = Parameter(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000678 Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400679 Node* base = HeapConstant(array);
680 Node* value =
681 Parameter(AccessBuilder::ForTypedArrayElement(type, true).type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682 Node* vector = UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400683 Node* context = UndefinedConstant();
684 Node* effect = graph()->start();
685 Node* control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686 VectorSlotPair feedback;
687 const Operator* op = javascript()->StoreProperty(language_mode, feedback);
688 Node* node = graph()->NewNode(op, base, key, value, vector, context,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100689 EmptyFrameState(), effect, control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400690 Reduction r = Reduce(node);
691
692 Matcher<Node*> offset_matcher =
693 element_size == 1
694 ? key
695 : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
696
697 ASSERT_TRUE(r.Changed());
698 EXPECT_THAT(
699 r.replacement(),
700 IsStoreBuffer(BufferAccess(type),
701 IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
702 offset_matcher,
703 IsNumberConstant(array->byte_length()->Number()), value,
704 effect, control));
705 }
706 }
707}
708
709
710TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) {
711 const size_t kLength = 17;
712 double backing_store[kLength];
713 Handle<JSArrayBuffer> buffer =
714 NewArrayBuffer(backing_store, sizeof(backing_store));
715 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400717 Handle<JSTypedArray> array =
718 factory()->NewJSTypedArray(type, buffer, 0, kLength);
719 int const element_size = static_cast<int>(array->element_size());
720
721 Node* key = Parameter(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722 Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400723 Node* base = HeapConstant(array);
724 Node* value = Parameter(Type::Any());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000725 Node* vector = UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400726 Node* context = UndefinedConstant();
727 Node* effect = graph()->start();
728 Node* control = graph()->start();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100729 // TODO(mstarzinger): Once the effect-control-linearizer provides a frame
730 // state we can get rid of this checkpoint again. The reducer won't care.
731 Node* checkpoint = graph()->NewNode(common()->Checkpoint(),
732 EmptyFrameState(), effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000733 VectorSlotPair feedback;
734 const Operator* op = javascript()->StoreProperty(language_mode, feedback);
735 Node* node = graph()->NewNode(op, base, key, value, vector, context,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100736 EmptyFrameState(), checkpoint, control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400737 Reduction r = Reduce(node);
738
739 Matcher<Node*> offset_matcher =
740 element_size == 1
741 ? key
742 : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
743
744 Matcher<Node*> value_matcher =
Ben Murdoch61f157c2016-09-16 13:49:30 +0100745 IsToNumber(value, context, checkpoint, control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400746 Matcher<Node*> effect_matcher = value_matcher;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400747
748 ASSERT_TRUE(r.Changed());
749 EXPECT_THAT(
750 r.replacement(),
751 IsStoreBuffer(BufferAccess(type),
752 IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
753 offset_matcher,
754 IsNumberConstant(array->byte_length()->Number()),
755 value_matcher, effect_matcher, control));
756 }
757 }
758}
759
760
761TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) {
762 const size_t kLength = 17;
763 double backing_store[kLength];
764 Handle<JSArrayBuffer> buffer =
765 NewArrayBuffer(backing_store, sizeof(backing_store));
766 TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400768 Handle<JSTypedArray> array =
769 factory()->NewJSTypedArray(type, buffer, 0, kLength);
770 ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
771
772 int min = random_number_generator()->NextInt(static_cast<int>(kLength));
773 int max = random_number_generator()->NextInt(static_cast<int>(kLength));
774 if (min > max) std::swap(min, max);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775 Node* key = Parameter(Type::Range(min, max, zone()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400776 Node* base = HeapConstant(array);
777 Node* value = Parameter(access.type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000778 Node* vector = UndefinedConstant();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400779 Node* context = UndefinedConstant();
780 Node* effect = graph()->start();
781 Node* control = graph()->start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782 VectorSlotPair feedback;
783 const Operator* op = javascript()->StoreProperty(language_mode, feedback);
784 Node* node = graph()->NewNode(op, base, key, value, vector, context,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100785 EmptyFrameState(), effect, control);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400786 Reduction r = Reduce(node);
787
788 ASSERT_TRUE(r.Changed());
789 EXPECT_THAT(
790 r.replacement(),
791 IsStoreElement(
792 access, IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
793 key, value, effect, control));
794 }
795 }
796}
797
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000798
799// -----------------------------------------------------------------------------
800// JSLoadNamed
801
802
803TEST_F(JSTypedLoweringTest, JSLoadNamedStringLength) {
804 VectorSlotPair feedback;
805 Handle<Name> name = factory()->length_string();
806 Node* const receiver = Parameter(Type::String(), 0);
807 Node* const vector = Parameter(Type::Internal(), 1);
808 Node* const context = UndefinedConstant();
809 Node* const effect = graph()->start();
810 Node* const control = graph()->start();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100811 Reduction const r = Reduce(
812 graph()->NewNode(javascript()->LoadNamed(name, feedback), receiver,
813 vector, context, EmptyFrameState(), effect, control));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100814 ASSERT_TRUE(r.Changed());
815 EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
816 receiver, effect, control));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000817}
818
819
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000820// -----------------------------------------------------------------------------
821// JSAdd
822
823
824TEST_F(JSTypedLoweringTest, JSAddWithString) {
825 BinaryOperationHints const hints = BinaryOperationHints::Any();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000826 Node* lhs = Parameter(Type::String(), 0);
827 Node* rhs = Parameter(Type::String(), 1);
828 Node* context = Parameter(Type::Any(), 2);
829 Node* frame_state0 = EmptyFrameState();
830 Node* frame_state1 = EmptyFrameState();
831 Node* effect = graph()->start();
832 Node* control = graph()->start();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100833 Reduction r =
834 Reduce(graph()->NewNode(javascript()->Add(hints), lhs, rhs, context,
835 frame_state0, frame_state1, effect, control));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000836 ASSERT_TRUE(r.Changed());
837 EXPECT_THAT(r.replacement(),
838 IsCall(_, IsHeapConstant(CodeFactory::StringAdd(
839 isolate(), STRING_ADD_CHECK_NONE,
840 NOT_TENURED).code()),
841 lhs, rhs, context, frame_state0, effect, control));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842}
843
Ben Murdoch61f157c2016-09-16 13:49:30 +0100844TEST_F(JSTypedLoweringTest, JSAddSmis) {
845 BinaryOperationHints const hints(BinaryOperationHints::kSignedSmall,
846 BinaryOperationHints::kSignedSmall,
847 BinaryOperationHints::kSignedSmall);
848 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
849 Node* lhs = Parameter(Type::Number(), 0);
850 Node* rhs = Parameter(Type::Number(), 1);
851 Node* context = Parameter(Type::Any(), 2);
852 Node* frame_state0 = EmptyFrameState();
853 Node* frame_state1 = EmptyFrameState();
854 Node* effect = graph()->start();
855 Node* control = graph()->start();
856 Reduction r =
857 Reduce(graph()->NewNode(javascript()->Add(hints), lhs, rhs, context,
858 frame_state0, frame_state1, effect, control));
859 ASSERT_TRUE(r.Changed());
860 EXPECT_THAT(r.replacement(),
861 IsSpeculativeNumberAdd(BinaryOperationHints::kSignedSmall, lhs,
862 rhs, effect, control));
863 }
864}
865
866// -----------------------------------------------------------------------------
867// JSSubtract
868
869TEST_F(JSTypedLoweringTest, JSSubtractSmis) {
870 BinaryOperationHints const hints(BinaryOperationHints::kSignedSmall,
871 BinaryOperationHints::kSignedSmall,
872 BinaryOperationHints::kSignedSmall);
873 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
874 Node* lhs = Parameter(Type::Number(), 0);
875 Node* rhs = Parameter(Type::Number(), 1);
876 Node* context = Parameter(Type::Any(), 2);
877 Node* frame_state0 = EmptyFrameState();
878 Node* frame_state1 = EmptyFrameState();
879 Node* effect = graph()->start();
880 Node* control = graph()->start();
881 Reduction r = Reduce(graph()->NewNode(javascript()->Subtract(hints), lhs,
882 rhs, context, frame_state0,
883 frame_state1, effect, control));
884 ASSERT_TRUE(r.Changed());
885 EXPECT_THAT(r.replacement(),
886 IsSpeculativeNumberSubtract(BinaryOperationHints::kSignedSmall,
887 lhs, rhs, effect, control));
888 }
889}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000890
891// -----------------------------------------------------------------------------
892// JSInstanceOf
893// Test that instanceOf is reduced if and only if the right-hand side is a
894// function constant. Functional correctness is ensured elsewhere.
895
896
897TEST_F(JSTypedLoweringTest, JSInstanceOfSpecializationWithoutSmiCheck) {
898 Node* const context = Parameter(Type::Any());
899 Node* const frame_state = EmptyFrameState();
900 Node* const effect = graph()->start();
901 Node* const control = graph()->start();
902
903 // Reduce if left-hand side is known to be an object.
904 Node* instanceOf =
905 graph()->NewNode(javascript()->InstanceOf(), Parameter(Type::Object(), 0),
906 HeapConstant(isolate()->object_function()), context,
907 frame_state, effect, control);
908 Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
909 frame_state, effect, control);
910 Reduction r = Reduce(instanceOf);
911 ASSERT_TRUE(r.Changed());
912 ASSERT_EQ(r.replacement(), dummy->InputAt(0));
913 ASSERT_NE(instanceOf, dummy->InputAt(0));
914}
915
916
917TEST_F(JSTypedLoweringTest, JSInstanceOfSpecializationWithSmiCheck) {
918 Node* const context = Parameter(Type::Any());
919 Node* const frame_state = EmptyFrameState();
920 Node* const effect = graph()->start();
921 Node* const control = graph()->start();
922
923 // Reduce if left-hand side could be a Smi.
924 Node* instanceOf =
925 graph()->NewNode(javascript()->InstanceOf(), Parameter(Type::Any(), 0),
926 HeapConstant(isolate()->object_function()), context,
927 frame_state, effect, control);
928 Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
929 frame_state, effect, control);
930 Reduction r = Reduce(instanceOf);
931 ASSERT_TRUE(r.Changed());
932 ASSERT_EQ(r.replacement(), dummy->InputAt(0));
933 ASSERT_NE(instanceOf, dummy->InputAt(0));
934}
935
936
937TEST_F(JSTypedLoweringTest, JSInstanceOfNoSpecialization) {
938 Node* const context = Parameter(Type::Any());
939 Node* const frame_state = EmptyFrameState();
940 Node* const effect = graph()->start();
941 Node* const control = graph()->start();
942
943 // Do not reduce if right-hand side is not a function constant.
944 Node* instanceOf = graph()->NewNode(
945 javascript()->InstanceOf(), Parameter(Type::Any(), 0),
946 Parameter(Type::Any()), context, frame_state, effect, control);
947 Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
948 frame_state, effect, control);
949 Reduction r = Reduce(instanceOf);
950 ASSERT_FALSE(r.Changed());
951 ASSERT_EQ(instanceOf, dummy->InputAt(0));
952}
953
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400954} // namespace compiler
955} // namespace internal
956} // namespace v8