Line data Source code
1 : // Copyright 2018 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include <cctype>
6 :
7 : #include "src/compiler/compilation-dependencies.h"
8 : #include "src/compiler/js-call-reducer.h"
9 : #include "src/compiler/js-graph.h"
10 : #include "src/compiler/simplified-operator.h"
11 : #include "src/feedback-vector.h"
12 : #include "src/heap/factory.h"
13 : #include "src/isolate.h"
14 : #include "test/unittests/compiler/graph-unittest.h"
15 : #include "test/unittests/compiler/node-test-utils.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace compiler {
20 :
21 : class JSCallReducerTest : public TypedGraphTest {
22 : public:
23 24 : JSCallReducerTest()
24 72 : : TypedGraphTest(3), javascript_(zone()), deps_(broker(), zone()) {
25 24 : broker()->SerializeStandardObjects();
26 24 : }
27 48 : ~JSCallReducerTest() override = default;
28 :
29 : protected:
30 50 : Reduction Reduce(Node* node) {
31 50 : MachineOperatorBuilder machine(zone());
32 50 : SimplifiedOperatorBuilder simplified(zone());
33 : JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
34 50 : &machine);
35 : // TODO(titzer): mock the GraphReducer here for better unit testing.
36 100 : GraphReducer graph_reducer(zone(), graph());
37 :
38 : JSCallReducer reducer(&graph_reducer, &jsgraph, broker(),
39 50 : JSCallReducer::kNoFlags, &deps_);
40 100 : return reducer.Reduce(node);
41 : }
42 :
43 100 : JSOperatorBuilder* javascript() { return &javascript_; }
44 :
45 2 : Node* GlobalFunction(const char* name) {
46 : Handle<JSFunction> f = Handle<JSFunction>::cast(
47 4 : Object::GetProperty(
48 : isolate(), isolate()->global_object(),
49 6 : isolate()->factory()->NewStringFromAsciiChecked(name))
50 : .ToHandleChecked());
51 2 : return HeapConstant(f);
52 : }
53 :
54 37 : Node* MathFunction(const std::string& name) {
55 : Handle<Object> m =
56 74 : JSObject::GetProperty(
57 : isolate(), isolate()->global_object(),
58 111 : isolate()->factory()->NewStringFromAsciiChecked("Math"))
59 37 : .ToHandleChecked();
60 : Handle<JSFunction> f = Handle<JSFunction>::cast(
61 74 : Object::GetProperty(
62 : isolate(), m,
63 74 : isolate()->factory()->NewStringFromAsciiChecked(name.c_str()))
64 : .ToHandleChecked());
65 37 : return HeapConstant(f);
66 : }
67 :
68 2 : Node* StringFunction(const char* name) {
69 : Handle<Object> m =
70 4 : JSObject::GetProperty(
71 : isolate(), isolate()->global_object(),
72 6 : isolate()->factory()->NewStringFromAsciiChecked("String"))
73 2 : .ToHandleChecked();
74 : Handle<JSFunction> f = Handle<JSFunction>::cast(
75 4 : Object::GetProperty(
76 4 : isolate(), m, isolate()->factory()->NewStringFromAsciiChecked(name))
77 : .ToHandleChecked());
78 2 : return HeapConstant(f);
79 : }
80 :
81 5 : Node* NumberFunction(const char* name) {
82 : Handle<Object> m =
83 10 : JSObject::GetProperty(
84 : isolate(), isolate()->global_object(),
85 15 : isolate()->factory()->NewStringFromAsciiChecked("Number"))
86 5 : .ToHandleChecked();
87 : Handle<JSFunction> f = Handle<JSFunction>::cast(
88 10 : Object::GetProperty(
89 10 : isolate(), m, isolate()->factory()->NewStringFromAsciiChecked(name))
90 : .ToHandleChecked());
91 5 : return HeapConstant(f);
92 : }
93 :
94 29 : std::string op_name_for(const char* fnc) {
95 29 : std::string string_fnc(fnc);
96 29 : char initial = std::toupper(fnc[0]);
97 87 : return std::string("Number") + initial +
98 116 : string_fnc.substr(1, std::string::npos);
99 : }
100 :
101 43 : const Operator* Call(int arity) {
102 : FeedbackVectorSpec spec(zone());
103 : spec.AddCallICSlot();
104 43 : Handle<FeedbackMetadata> metadata = FeedbackMetadata::New(isolate(), &spec);
105 : Handle<SharedFunctionInfo> shared =
106 : isolate()->factory()->NewSharedFunctionInfoForBuiltin(
107 43 : isolate()->factory()->empty_string(), Builtins::kIllegal);
108 : // Set the raw feedback metadata to circumvent checks that we are not
109 : // overwriting existing metadata.
110 86 : shared->set_raw_outer_scope_info_or_feedback_metadata(*metadata);
111 : Handle<ClosureFeedbackCellArray> closure_feedback_cell_array =
112 43 : ClosureFeedbackCellArray::New(isolate(), shared);
113 : Handle<FeedbackVector> vector =
114 43 : FeedbackVector::New(isolate(), shared, closure_feedback_cell_array);
115 : VectorSlotPair feedback(vector, FeedbackSlot(0), UNINITIALIZED);
116 86 : return javascript()->Call(arity, CallFrequency(), feedback,
117 : ConvertReceiverMode::kAny,
118 86 : SpeculationMode::kAllowSpeculation);
119 : }
120 :
121 : private:
122 : JSOperatorBuilder javascript_;
123 : CompilationDependencies deps_;
124 : };
125 :
126 15444 : TEST_F(JSCallReducerTest, PromiseConstructorNoArgs) {
127 : Node* promise =
128 2 : HeapConstant(handle(native_context()->promise_function(), isolate()));
129 : Node* effect = graph()->start();
130 : Node* control = graph()->start();
131 1 : Node* context = UndefinedConstant();
132 : Node* frame_state = graph()->start();
133 :
134 : Node* construct =
135 3 : graph()->NewNode(javascript()->Construct(2), promise, promise, context,
136 : frame_state, effect, control);
137 :
138 1 : Reduction r = Reduce(construct);
139 :
140 2 : ASSERT_FALSE(r.Changed());
141 : }
142 :
143 15444 : TEST_F(JSCallReducerTest, PromiseConstructorSubclass) {
144 : Node* promise =
145 2 : HeapConstant(handle(native_context()->promise_function(), isolate()));
146 : Node* new_target =
147 2 : HeapConstant(handle(native_context()->array_function(), isolate()));
148 : Node* effect = graph()->start();
149 : Node* control = graph()->start();
150 1 : Node* context = UndefinedConstant();
151 : Node* frame_state = graph()->start();
152 :
153 1 : Node* executor = UndefinedConstant();
154 : Node* construct =
155 3 : graph()->NewNode(javascript()->Construct(3), promise, executor,
156 : new_target, context, frame_state, effect, control);
157 :
158 1 : Reduction r = Reduce(construct);
159 :
160 2 : ASSERT_FALSE(r.Changed());
161 : }
162 :
163 15444 : TEST_F(JSCallReducerTest, PromiseConstructorBasic) {
164 : Node* promise =
165 2 : HeapConstant(handle(native_context()->promise_function(), isolate()));
166 : Node* effect = graph()->start();
167 : Node* control = graph()->start();
168 1 : Node* context = UndefinedConstant();
169 : Node* frame_state = graph()->start();
170 :
171 1 : Node* executor = UndefinedConstant();
172 : Node* construct =
173 3 : graph()->NewNode(javascript()->Construct(3), promise, executor, promise,
174 : context, frame_state, effect, control);
175 :
176 1 : Reduction r = Reduce(construct);
177 :
178 1 : if (FLAG_experimental_inline_promise_constructor) {
179 1 : ASSERT_TRUE(r.Changed());
180 : } else {
181 0 : ASSERT_FALSE(r.Changed());
182 : }
183 : }
184 :
185 : // Exactly the same as PromiseConstructorBasic which expects a reduction,
186 : // except that we invalidate the protector cell.
187 15444 : TEST_F(JSCallReducerTest, PromiseConstructorWithHook) {
188 : Node* promise =
189 2 : HeapConstant(handle(native_context()->promise_function(), isolate()));
190 : Node* effect = graph()->start();
191 : Node* control = graph()->start();
192 1 : Node* context = UndefinedConstant();
193 : Node* frame_state = graph()->start();
194 :
195 1 : Node* executor = UndefinedConstant();
196 : Node* construct =
197 3 : graph()->NewNode(javascript()->Construct(3), promise, executor, promise,
198 : context, frame_state, effect, control);
199 :
200 1 : isolate()->InvalidatePromiseHookProtector();
201 :
202 1 : Reduction r = Reduce(construct);
203 :
204 2 : ASSERT_FALSE(r.Changed());
205 : }
206 :
207 : // -----------------------------------------------------------------------------
208 : // Math unaries
209 :
210 : namespace {
211 :
212 : const char* kMathUnaries[] = {
213 : "abs", "acos", "acosh", "asin", "asinh", "atan", "cbrt",
214 : "ceil", "cos", "cosh", "exp", "expm1", "floor", "fround",
215 : "log", "log1p", "log10", "log2", "round", "sign", "sin",
216 : "sinh", "sqrt", "tan", "tanh", "trunc"};
217 :
218 : } // namespace
219 :
220 15444 : TEST_F(JSCallReducerTest, MathUnaryWithNumber) {
221 105 : TRACED_FOREACH(const char*, fnc, kMathUnaries) {
222 : Node* effect = graph()->start();
223 : Node* control = graph()->start();
224 26 : Node* context = UndefinedConstant();
225 : Node* frame_state = graph()->start();
226 52 : Node* jsfunction = MathFunction(fnc);
227 26 : Node* p0 = Parameter(Type::Any(), 0);
228 26 : Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0,
229 : context, frame_state, effect, control);
230 26 : Reduction r = Reduce(call);
231 26 : ASSERT_TRUE(r.Changed());
232 104 : EXPECT_THAT(std::string(IrOpcode::Mnemonic(r.replacement()->opcode())),
233 0 : op_name_for(fnc));
234 : }
235 : }
236 :
237 : // -----------------------------------------------------------------------------
238 : // Math binaries
239 :
240 : namespace {
241 :
242 : const char* kMathBinaries[] = {"atan2", "pow"};
243 :
244 : } // namespace
245 :
246 15444 : TEST_F(JSCallReducerTest, MathBinaryWithNumber) {
247 9 : TRACED_FOREACH(const char*, fnc, kMathBinaries) {
248 4 : Node* jsfunction = MathFunction(fnc);
249 :
250 : Node* effect = graph()->start();
251 : Node* control = graph()->start();
252 2 : Node* context = UndefinedConstant();
253 : Node* frame_state = graph()->start();
254 2 : Node* p0 = Parameter(Type::Any(), 0);
255 2 : Node* p1 = Parameter(Type::Any(), 0);
256 2 : Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0,
257 : p1, context, frame_state, effect, control);
258 2 : Reduction r = Reduce(call);
259 :
260 2 : ASSERT_TRUE(r.Changed());
261 8 : EXPECT_THAT(std::string(IrOpcode::Mnemonic(r.replacement()->opcode())),
262 0 : op_name_for(fnc));
263 : }
264 : }
265 :
266 : // -----------------------------------------------------------------------------
267 : // Math.clz32
268 :
269 15444 : TEST_F(JSCallReducerTest, MathClz32WithUnsigned32) {
270 2 : Node* jsfunction = MathFunction("clz32");
271 : Node* effect = graph()->start();
272 : Node* control = graph()->start();
273 1 : Node* context = UndefinedConstant();
274 : Node* frame_state = graph()->start();
275 :
276 1 : Node* p0 = Parameter(Type::Unsigned32(), 0);
277 1 : Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0,
278 : context, frame_state, effect, control);
279 1 : Reduction r = Reduce(call);
280 :
281 1 : ASSERT_TRUE(r.Changed());
282 7 : EXPECT_THAT(r.replacement(),
283 0 : IsNumberClz32(IsNumberToUint32(IsSpeculativeToNumber(p0))));
284 : }
285 :
286 15444 : TEST_F(JSCallReducerTest, MathClz32WithUnsigned32NoArg) {
287 2 : Node* jsfunction = MathFunction("clz32");
288 : Node* effect = graph()->start();
289 : Node* control = graph()->start();
290 1 : Node* context = UndefinedConstant();
291 : Node* frame_state = graph()->start();
292 :
293 1 : Node* call = graph()->NewNode(Call(2), jsfunction, UndefinedConstant(),
294 : context, frame_state, effect, control);
295 1 : Reduction r = Reduce(call);
296 :
297 1 : ASSERT_TRUE(r.Changed());
298 5 : EXPECT_THAT(r.replacement(), IsNumberConstant(32));
299 : }
300 :
301 : // -----------------------------------------------------------------------------
302 : // Math.imul
303 :
304 15444 : TEST_F(JSCallReducerTest, MathImulWithUnsigned32) {
305 2 : Node* jsfunction = MathFunction("imul");
306 :
307 : Node* effect = graph()->start();
308 : Node* control = graph()->start();
309 1 : Node* context = UndefinedConstant();
310 : Node* frame_state = graph()->start();
311 1 : Node* p0 = Parameter(Type::Unsigned32(), 0);
312 1 : Node* p1 = Parameter(Type::Unsigned32(), 1);
313 1 : Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0,
314 : p1, context, frame_state, effect, control);
315 1 : Reduction r = Reduce(call);
316 :
317 1 : ASSERT_TRUE(r.Changed());
318 4 : EXPECT_THAT(std::string(IrOpcode::Mnemonic(r.replacement()->opcode())),
319 0 : op_name_for("imul"));
320 : }
321 :
322 : // -----------------------------------------------------------------------------
323 : // Math.min
324 :
325 15444 : TEST_F(JSCallReducerTest, MathMinWithNoArguments) {
326 2 : Node* jsfunction = MathFunction("min");
327 : Node* effect = graph()->start();
328 : Node* control = graph()->start();
329 1 : Node* context = UndefinedConstant();
330 : Node* frame_state = graph()->start();
331 1 : Node* call = graph()->NewNode(Call(2), jsfunction, UndefinedConstant(),
332 : context, frame_state, effect, control);
333 1 : Reduction r = Reduce(call);
334 :
335 1 : ASSERT_TRUE(r.Changed());
336 5 : EXPECT_THAT(r.replacement(), IsNumberConstant(V8_INFINITY));
337 : }
338 :
339 15444 : TEST_F(JSCallReducerTest, MathMinWithNumber) {
340 2 : Node* jsfunction = MathFunction("min");
341 : Node* effect = graph()->start();
342 : Node* control = graph()->start();
343 1 : Node* context = UndefinedConstant();
344 : Node* frame_state = graph()->start();
345 1 : Node* p0 = Parameter(Type::Any(), 0);
346 1 : Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0,
347 : context, frame_state, effect, control);
348 1 : Reduction r = Reduce(call);
349 :
350 1 : ASSERT_TRUE(r.Changed());
351 5 : EXPECT_THAT(r.replacement(), IsSpeculativeToNumber(p0));
352 : }
353 :
354 15444 : TEST_F(JSCallReducerTest, MathMinWithTwoArguments) {
355 2 : Node* jsfunction = MathFunction("min");
356 : Node* effect = graph()->start();
357 : Node* control = graph()->start();
358 1 : Node* context = UndefinedConstant();
359 : Node* frame_state = graph()->start();
360 1 : Node* p0 = Parameter(Type::Any(), 0);
361 1 : Node* p1 = Parameter(Type::Any(), 1);
362 1 : Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0,
363 : p1, context, frame_state, effect, control);
364 1 : Reduction r = Reduce(call);
365 :
366 1 : ASSERT_TRUE(r.Changed());
367 8 : EXPECT_THAT(r.replacement(), IsNumberMin(IsSpeculativeToNumber(p0),
368 0 : IsSpeculativeToNumber(p1)));
369 : }
370 :
371 : // -----------------------------------------------------------------------------
372 : // Math.max
373 :
374 15444 : TEST_F(JSCallReducerTest, MathMaxWithNoArguments) {
375 2 : Node* jsfunction = MathFunction("max");
376 :
377 : Node* effect = graph()->start();
378 : Node* control = graph()->start();
379 1 : Node* context = UndefinedConstant();
380 : Node* frame_state = graph()->start();
381 1 : Node* call = graph()->NewNode(Call(2), jsfunction, UndefinedConstant(),
382 : context, frame_state, effect, control);
383 1 : Reduction r = Reduce(call);
384 :
385 1 : ASSERT_TRUE(r.Changed());
386 5 : EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
387 : }
388 :
389 15444 : TEST_F(JSCallReducerTest, MathMaxWithNumber) {
390 2 : Node* jsfunction = MathFunction("max");
391 : Node* effect = graph()->start();
392 : Node* control = graph()->start();
393 1 : Node* context = UndefinedConstant();
394 : Node* frame_state = graph()->start();
395 1 : Node* p0 = Parameter(Type::Any(), 0);
396 1 : Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0,
397 : context, frame_state, effect, control);
398 1 : Reduction r = Reduce(call);
399 :
400 1 : ASSERT_TRUE(r.Changed());
401 5 : EXPECT_THAT(r.replacement(), IsSpeculativeToNumber(p0));
402 : }
403 :
404 15444 : TEST_F(JSCallReducerTest, MathMaxWithTwoArguments) {
405 2 : Node* jsfunction = MathFunction("max");
406 :
407 : Node* effect = graph()->start();
408 : Node* control = graph()->start();
409 1 : Node* context = UndefinedConstant();
410 : Node* frame_state = graph()->start();
411 1 : Node* p0 = Parameter(Type::Any(), 0);
412 1 : Node* p1 = Parameter(Type::Any(), 1);
413 1 : Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0,
414 : p1, context, frame_state, effect, control);
415 1 : Reduction r = Reduce(call);
416 :
417 1 : ASSERT_TRUE(r.Changed());
418 8 : EXPECT_THAT(r.replacement(), IsNumberMax(IsSpeculativeToNumber(p0),
419 0 : IsSpeculativeToNumber(p1)));
420 : }
421 :
422 : // -----------------------------------------------------------------------------
423 : // String.fromCharCode
424 :
425 15444 : TEST_F(JSCallReducerTest, StringFromSingleCharCodeWithNumber) {
426 1 : Node* function = StringFunction("fromCharCode");
427 :
428 : Node* effect = graph()->start();
429 : Node* control = graph()->start();
430 1 : Node* context = UndefinedConstant();
431 : Node* frame_state = graph()->start();
432 1 : Node* p0 = Parameter(Type::Any(), 0);
433 1 : Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0,
434 : context, frame_state, effect, control);
435 1 : Reduction r = Reduce(call);
436 :
437 1 : ASSERT_TRUE(r.Changed());
438 6 : EXPECT_THAT(r.replacement(),
439 0 : IsStringFromSingleCharCode(IsSpeculativeToNumber(p0)));
440 : }
441 :
442 15444 : TEST_F(JSCallReducerTest, StringFromSingleCharCodeWithPlainPrimitive) {
443 1 : Node* function = StringFunction("fromCharCode");
444 :
445 : Node* effect = graph()->start();
446 : Node* control = graph()->start();
447 1 : Node* context = UndefinedConstant();
448 : Node* frame_state = graph()->start();
449 1 : Node* p0 = Parameter(Type::PlainPrimitive(), 0);
450 1 : Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0,
451 : context, frame_state, effect, control);
452 1 : Reduction r = Reduce(call);
453 :
454 1 : ASSERT_TRUE(r.Changed());
455 6 : EXPECT_THAT(r.replacement(),
456 0 : IsStringFromSingleCharCode(IsSpeculativeToNumber(p0)));
457 : }
458 :
459 : // -----------------------------------------------------------------------------
460 : // Number.isFinite
461 :
462 15444 : TEST_F(JSCallReducerTest, NumberIsFinite) {
463 1 : Node* function = NumberFunction("isFinite");
464 :
465 : Node* effect = graph()->start();
466 : Node* control = graph()->start();
467 1 : Node* context = UndefinedConstant();
468 : Node* frame_state = graph()->start();
469 1 : Node* p0 = Parameter(Type::Any(), 0);
470 1 : Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0,
471 : context, frame_state, effect, control);
472 1 : Reduction r = Reduce(call);
473 :
474 1 : ASSERT_TRUE(r.Changed());
475 5 : EXPECT_THAT(r.replacement(), IsObjectIsFiniteNumber(p0));
476 : }
477 :
478 : // -----------------------------------------------------------------------------
479 : // Number.isInteger
480 :
481 15444 : TEST_F(JSCallReducerTest, NumberIsIntegerWithNumber) {
482 1 : Node* function = NumberFunction("isInteger");
483 :
484 : Node* effect = graph()->start();
485 : Node* control = graph()->start();
486 1 : Node* context = UndefinedConstant();
487 : Node* frame_state = graph()->start();
488 1 : Node* p0 = Parameter(Type::Any(), 0);
489 : Node* call =
490 3 : graph()->NewNode(javascript()->Call(3), function, UndefinedConstant(), p0,
491 : context, frame_state, effect, control);
492 1 : Reduction r = Reduce(call);
493 :
494 1 : ASSERT_TRUE(r.Changed());
495 5 : EXPECT_THAT(r.replacement(), IsObjectIsInteger(p0));
496 : }
497 :
498 : // -----------------------------------------------------------------------------
499 : // Number.isNaN
500 :
501 15444 : TEST_F(JSCallReducerTest, NumberIsNaNWithNumber) {
502 1 : Node* function = NumberFunction("isNaN");
503 :
504 : Node* effect = graph()->start();
505 : Node* control = graph()->start();
506 1 : Node* context = UndefinedConstant();
507 : Node* frame_state = graph()->start();
508 1 : Node* p0 = Parameter(Type::Any(), 0);
509 : Node* call =
510 3 : graph()->NewNode(javascript()->Call(3), function, UndefinedConstant(), p0,
511 : context, frame_state, effect, control);
512 1 : Reduction r = Reduce(call);
513 :
514 1 : ASSERT_TRUE(r.Changed());
515 5 : EXPECT_THAT(r.replacement(), IsObjectIsNaN(p0));
516 : }
517 :
518 : // -----------------------------------------------------------------------------
519 : // Number.isSafeInteger
520 :
521 15444 : TEST_F(JSCallReducerTest, NumberIsSafeIntegerWithIntegral32) {
522 1 : Node* function = NumberFunction("isSafeInteger");
523 :
524 : Node* effect = graph()->start();
525 : Node* control = graph()->start();
526 1 : Node* context = UndefinedConstant();
527 : Node* frame_state = graph()->start();
528 1 : Node* p0 = Parameter(Type::Any(), 0);
529 : Node* call =
530 3 : graph()->NewNode(javascript()->Call(3), function, UndefinedConstant(), p0,
531 : context, frame_state, effect, control);
532 1 : Reduction r = Reduce(call);
533 :
534 1 : ASSERT_TRUE(r.Changed());
535 5 : EXPECT_THAT(r.replacement(), IsObjectIsSafeInteger(p0));
536 : }
537 :
538 : // -----------------------------------------------------------------------------
539 : // isFinite
540 :
541 15444 : TEST_F(JSCallReducerTest, GlobalIsFiniteWithNumber) {
542 1 : Node* function = GlobalFunction("isFinite");
543 :
544 : Node* effect = graph()->start();
545 : Node* control = graph()->start();
546 1 : Node* context = UndefinedConstant();
547 : Node* frame_state = graph()->start();
548 1 : Node* p0 = Parameter(Type::Any(), 0);
549 1 : Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0,
550 : context, frame_state, effect, control);
551 1 : Reduction r = Reduce(call);
552 :
553 1 : ASSERT_TRUE(r.Changed());
554 6 : EXPECT_THAT(r.replacement(), IsNumberIsFinite(IsSpeculativeToNumber(p0)));
555 : }
556 :
557 : // -----------------------------------------------------------------------------
558 : // isNaN
559 :
560 15444 : TEST_F(JSCallReducerTest, GlobalIsNaN) {
561 1 : Node* function = GlobalFunction("isNaN");
562 :
563 : Node* effect = graph()->start();
564 : Node* control = graph()->start();
565 1 : Node* context = UndefinedConstant();
566 : Node* frame_state = graph()->start();
567 1 : Node* p0 = Parameter(Type::Any(), 0);
568 1 : Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0,
569 : context, frame_state, effect, control);
570 1 : Reduction r = Reduce(call);
571 :
572 1 : ASSERT_TRUE(r.Changed());
573 6 : EXPECT_THAT(r.replacement(), IsNumberIsNaN(IsSpeculativeToNumber(p0)));
574 : }
575 :
576 : // -----------------------------------------------------------------------------
577 : // Number.parseInt
578 :
579 15444 : TEST_F(JSCallReducerTest, NumberParseInt) {
580 1 : Node* function = NumberFunction("parseInt");
581 :
582 : Node* effect = graph()->start();
583 : Node* control = graph()->start();
584 1 : Node* context = UndefinedConstant();
585 : Node* frame_state = graph()->start();
586 1 : Node* p0 = Parameter(Type::Any(), 0);
587 1 : Node* p1 = Parameter(Type::Any(), 1);
588 1 : Node* call = graph()->NewNode(Call(4), function, UndefinedConstant(), p0, p1,
589 : context, frame_state, effect, control);
590 1 : Reduction r = Reduce(call);
591 :
592 1 : ASSERT_TRUE(r.Changed());
593 6 : EXPECT_THAT(r.replacement(), IsJSParseInt(p0, p1));
594 : }
595 :
596 : } // namespace compiler
597 : } // namespace internal
598 9264 : } // namespace v8
|