1 | // Copyright 2017 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #include "src/builtins/builtins-utils-gen.h" |
6 | #include "src/builtins/builtins.h" |
7 | #include "src/code-stub-assembler.h" |
8 | |
9 | namespace v8 { |
10 | namespace internal { |
11 | |
12 | // ES #sec-isfinite-number |
13 | TF_BUILTIN(GlobalIsFinite, CodeStubAssembler) { |
14 | Node* context = Parameter(Descriptor::kContext); |
15 | |
16 | Label return_true(this), return_false(this); |
17 | |
18 | // We might need to loop once for ToNumber conversion. |
19 | VARIABLE(var_num, MachineRepresentation::kTagged); |
20 | Label loop(this, &var_num); |
21 | var_num.Bind(Parameter(Descriptor::kNumber)); |
22 | Goto(&loop); |
23 | BIND(&loop); |
24 | { |
25 | Node* num = var_num.value(); |
26 | |
27 | // Check if {num} is a Smi or a HeapObject. |
28 | GotoIf(TaggedIsSmi(num), &return_true); |
29 | |
30 | // Check if {num} is a HeapNumber. |
31 | Label if_numisheapnumber(this), |
32 | if_numisnotheapnumber(this, Label::kDeferred); |
33 | Branch(IsHeapNumber(num), &if_numisheapnumber, &if_numisnotheapnumber); |
34 | |
35 | BIND(&if_numisheapnumber); |
36 | { |
37 | // Check if {num} contains a finite, non-NaN value. |
38 | Node* num_value = LoadHeapNumberValue(num); |
39 | BranchIfFloat64IsNaN(Float64Sub(num_value, num_value), &return_false, |
40 | &return_true); |
41 | } |
42 | |
43 | BIND(&if_numisnotheapnumber); |
44 | { |
45 | // Need to convert {num} to a Number first. |
46 | var_num.Bind(CallBuiltin(Builtins::kNonNumberToNumber, context, num)); |
47 | Goto(&loop); |
48 | } |
49 | } |
50 | |
51 | BIND(&return_true); |
52 | Return(TrueConstant()); |
53 | |
54 | BIND(&return_false); |
55 | Return(FalseConstant()); |
56 | } |
57 | |
58 | // ES6 #sec-isnan-number |
59 | TF_BUILTIN(GlobalIsNaN, CodeStubAssembler) { |
60 | Node* context = Parameter(Descriptor::kContext); |
61 | |
62 | Label return_true(this), return_false(this); |
63 | |
64 | // We might need to loop once for ToNumber conversion. |
65 | VARIABLE(var_num, MachineRepresentation::kTagged); |
66 | Label loop(this, &var_num); |
67 | var_num.Bind(Parameter(Descriptor::kNumber)); |
68 | Goto(&loop); |
69 | BIND(&loop); |
70 | { |
71 | Node* num = var_num.value(); |
72 | |
73 | // Check if {num} is a Smi or a HeapObject. |
74 | GotoIf(TaggedIsSmi(num), &return_false); |
75 | |
76 | // Check if {num} is a HeapNumber. |
77 | Label if_numisheapnumber(this), |
78 | if_numisnotheapnumber(this, Label::kDeferred); |
79 | Branch(IsHeapNumber(num), &if_numisheapnumber, &if_numisnotheapnumber); |
80 | |
81 | BIND(&if_numisheapnumber); |
82 | { |
83 | // Check if {num} contains a NaN. |
84 | Node* num_value = LoadHeapNumberValue(num); |
85 | BranchIfFloat64IsNaN(num_value, &return_true, &return_false); |
86 | } |
87 | |
88 | BIND(&if_numisnotheapnumber); |
89 | { |
90 | // Need to convert {num} to a Number first. |
91 | var_num.Bind(CallBuiltin(Builtins::kNonNumberToNumber, context, num)); |
92 | Goto(&loop); |
93 | } |
94 | } |
95 | |
96 | BIND(&return_true); |
97 | Return(TrueConstant()); |
98 | |
99 | BIND(&return_false); |
100 | Return(FalseConstant()); |
101 | } |
102 | |
103 | } // namespace internal |
104 | } // namespace v8 |
105 | |