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/codegen/code-stub-assembler.h"
8
9 namespace v8 {
10 namespace internal {
11
12 // ES #sec-isfinite-number
TF_BUILTIN(GlobalIsFinite,CodeStubAssembler)13 TF_BUILTIN(GlobalIsFinite, CodeStubAssembler) {
14 auto context = Parameter<Context>(Descriptor::kContext);
15
16 Label return_true(this), return_false(this);
17
18 // We might need to loop once for ToNumber conversion.
19 TVARIABLE(Object, var_num);
20 Label loop(this, &var_num);
21 var_num = Parameter<Object>(Descriptor::kNumber);
22 Goto(&loop);
23 BIND(&loop);
24 {
25 TNode<Object> num = var_num.value();
26
27 // Check if {num} is a Smi or a HeapObject.
28 GotoIf(TaggedIsSmi(num), &return_true);
29 TNode<HeapObject> num_heap_object = CAST(num);
30
31 // Check if {num_heap_object} is a HeapNumber.
32 Label if_numisheapnumber(this),
33 if_numisnotheapnumber(this, Label::kDeferred);
34 Branch(IsHeapNumber(num_heap_object), &if_numisheapnumber,
35 &if_numisnotheapnumber);
36
37 BIND(&if_numisheapnumber);
38 {
39 // Check if {num_heap_object} contains a finite, non-NaN value.
40 TNode<Float64T> num_value = LoadHeapNumberValue(num_heap_object);
41 BranchIfFloat64IsNaN(Float64Sub(num_value, num_value), &return_false,
42 &return_true);
43 }
44
45 BIND(&if_numisnotheapnumber);
46 {
47 // Need to convert {num_heap_object} to a Number first.
48 var_num =
49 CallBuiltin(Builtin::kNonNumberToNumber, context, num_heap_object);
50 Goto(&loop);
51 }
52 }
53
54 BIND(&return_true);
55 Return(TrueConstant());
56
57 BIND(&return_false);
58 Return(FalseConstant());
59 }
60
61 // ES6 #sec-isnan-number
TF_BUILTIN(GlobalIsNaN,CodeStubAssembler)62 TF_BUILTIN(GlobalIsNaN, CodeStubAssembler) {
63 auto context = Parameter<Context>(Descriptor::kContext);
64
65 Label return_true(this), return_false(this);
66
67 // We might need to loop once for ToNumber conversion.
68 TVARIABLE(Object, var_num);
69 Label loop(this, &var_num);
70 var_num = Parameter<Object>(Descriptor::kNumber);
71 Goto(&loop);
72 BIND(&loop);
73 {
74 TNode<Object> num = var_num.value();
75
76 // Check if {num} is a Smi or a HeapObject.
77 GotoIf(TaggedIsSmi(num), &return_false);
78 TNode<HeapObject> num_heap_object = CAST(num);
79
80 // Check if {num_heap_object} is a HeapNumber.
81 Label if_numisheapnumber(this),
82 if_numisnotheapnumber(this, Label::kDeferred);
83 Branch(IsHeapNumber(num_heap_object), &if_numisheapnumber,
84 &if_numisnotheapnumber);
85
86 BIND(&if_numisheapnumber);
87 {
88 // Check if {num_heap_object} contains a NaN.
89 TNode<Float64T> num_value = LoadHeapNumberValue(num_heap_object);
90 BranchIfFloat64IsNaN(num_value, &return_true, &return_false);
91 }
92
93 BIND(&if_numisnotheapnumber);
94 {
95 // Need to convert {num_heap_object} to a Number first.
96 var_num =
97 CallBuiltin(Builtin::kNonNumberToNumber, context, num_heap_object);
98 Goto(&loop);
99 }
100 }
101
102 BIND(&return_true);
103 Return(TrueConstant());
104
105 BIND(&return_false);
106 Return(FalseConstant());
107 }
108
109 } // namespace internal
110 } // namespace v8
111