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