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