• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_JS_NUMBER_H
17 #define ECMASCRIPT_JS_NUMBER_H
18 
19 #include "ecmascript/base/number_helper.h"
20 
21 #include "ecmascript/ecma_macros.h"
22 #include "ecmascript/ecma_vm.h"
23 #include "ecmascript/js_hclass.h"
24 #include "ecmascript/js_tagged_value.h"
25 #include "ecmascript/object_factory.h"
26 
27 namespace panda {
28 namespace ecmascript {
29 class JSTaggedNumber final : public JSTaggedValue {
30 public:
31     constexpr JSTaggedNumber() = default;
JSTaggedNumber(double v)32     explicit JSTaggedNumber(double v) : JSTaggedValue(v) {}
JSTaggedNumber(int v)33     constexpr explicit JSTaggedNumber(int v) : JSTaggedValue(v) {}
JSTaggedNumber(unsigned int v)34     explicit JSTaggedNumber(unsigned int v) : JSTaggedValue(v) {}
JSTaggedNumber(JSTaggedValue v)35     explicit JSTaggedNumber(JSTaggedValue v) : JSTaggedValue(v.GetRawData())
36     {
37         ASSERT_PRINT(v.IsNumber(), "can not convert non Number JSTaggedValue to JSTaggedNumber");
38     }
39 
40     ~JSTaggedNumber() = default;
41     DEFAULT_COPY_SEMANTIC(JSTaggedNumber);
42     DEFAULT_MOVE_SEMANTIC(JSTaggedNumber);
43 
Exception()44     static inline constexpr JSTaggedNumber Exception()
45     {
46         return JSTaggedNumber(VALUE_EXCEPTION);
47     }
48 
IsException()49     inline bool IsException() const
50     {
51         return JSTaggedValue::IsException();
52     }
53 
ToInt32()54     inline int32_t ToInt32() const
55     {
56         if (IsInt()) {
57             return GetInt();
58         }
59         return base::NumberHelper::DoubleToInt(GetDouble(), base::INT32_BITS);
60     }
61 
ToUint32()62     inline uint32_t ToUint32() const
63     {
64         return ToInt32();
65     }
66 
ToInt16()67     inline int16_t ToInt16() const
68     {
69         return base::NumberHelper::DoubleToInt(GetNumber(), base::INT16_BITS);
70     }
71 
ToUint16()72     inline uint16_t ToUint16() const
73     {
74         return ToInt16();
75     }
76 
ToInt8()77     inline int8_t ToInt8() const
78     {
79         return base::NumberHelper::DoubleToInt(GetNumber(), base::INT8_BITS);
80     }
81 
ToUint8()82     inline uint8_t ToUint8() const
83     {
84         return ToInt8();
85     }
86 
ToString(const JSThread * thread)87     inline JSHandle<EcmaString> ToString(const JSThread *thread) const
88     {
89         return base::NumberHelper::NumberToString(thread, *this);
90     }
91 
92     JSTaggedNumber operator-(JSTaggedNumber number) const
93     {
94         if (IsInt() && number.IsInt()) {
95             int64_t a0 = GetInt();
96             int64_t a1 = number.GetInt();
97             int64_t res = a0 - a1;
98             if (res > INT32_MAX || res < INT32_MIN) {
99                 return JSTaggedNumber(static_cast<double>(res));
100             }
101             return JSTaggedNumber(static_cast<int>(res));
102         }
103         return JSTaggedNumber(GetNumber() - number.GetNumber());
104     }
105 
106     JSTaggedNumber operator*(JSTaggedNumber number) const
107     {
108         if (IsInt() && number.IsInt()) {
109             int64_t intA = GetInt();
110             int64_t intB = number.GetInt();
111             int64_t res = intA * intB;
112             if (res > INT32_MAX || res < INT32_MIN) {
113                 return JSTaggedNumber(static_cast<double>(res));
114             }
115             return JSTaggedNumber(static_cast<int>(res));
116         }
117         return JSTaggedNumber(GetNumber() * number.GetNumber());
118     }
119 
120     JSTaggedNumber operator++() const
121     {
122         if (IsInt()) {
123             int32_t value = GetInt();
124             if (value == INT32_MAX) {
125                 return JSTaggedNumber(static_cast<double>(value) + 1.0);
126             }
127             return JSTaggedNumber(value + 1);
128         }
129         return JSTaggedNumber(GetDouble() + 1.0);
130     }
131 
132     JSTaggedNumber operator--() const
133     {
134         if (IsInt()) {
135             int32_t value = GetInt();
136             if (value == INT32_MIN) {
137                 return JSTaggedNumber(static_cast<double>(value) - 1.0);
138             }
139             return JSTaggedNumber(value - 1);
140         }
141         return JSTaggedNumber(GetDouble() - 1.0);
142     }
143 
144     inline bool operator!=(const JSTaggedNumber &number) const
145     {
146         return GetNumber() != number.GetNumber();
147     }
148 
149     /* static */
SameValue(JSTaggedNumber x,JSTaggedNumber y)150     inline static bool SameValue(JSTaggedNumber x, JSTaggedNumber y)
151     {
152         double xValue = x.GetNumber();
153         double yValue = y.GetNumber();
154         // SameNumberValue(NaN, NaN) is true.
155         if (xValue != yValue) {
156             return std::isnan(xValue) && std::isnan(yValue);
157         }
158         // SameNumberValue(0.0, -0.0) is false.
159         return (std::signbit(xValue) == std::signbit(yValue));
160     }
161 
FromIntOrDouble(JSThread * thread,JSTaggedValue tagged)162     inline static JSTaggedNumber FromIntOrDouble(JSThread *thread, JSTaggedValue tagged)
163     {
164         if (tagged.IsInt() || tagged.IsDouble()) {
165             return JSTaggedNumber(tagged);
166         }
167         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert value to a number", JSTaggedNumber::Exception());
168     }
169 
170 private:
JSTaggedNumber(JSTaggedType v)171     constexpr explicit JSTaggedNumber(JSTaggedType v) : JSTaggedValue(v) {}
172 };
173 }  // namespace ecmascript
174 }  // namespace panda
175 #endif  // ECMASCRIPT_JS_NUMBER_H
176