1 /* 2 * Copyright (c) 2023 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_NUMBER_GATE_INFO_H 17 #define ECMASCRIPT_NUMBER_GATE_INFO_H 18 #include "ecmascript/compiler/gate_accessor.h" 19 #include "ecmascript/js_hclass.h" 20 #include "ecmascript/js_typed_array.h" 21 22 namespace panda::ecmascript::kungfu { 23 24 enum class TypeInfo { 25 NONE, 26 INT1, 27 INT32, 28 UINT32, 29 FLOAT64, 30 TAGGED, 31 }; 32 33 class UseInfo { 34 public: UseInfo(uint8_t tag)35 UseInfo(uint8_t tag) : tag_(tag) {} 36 static constexpr uint8_t UNUSED = 0; 37 static constexpr uint8_t BOOL = 1 << 0; 38 static constexpr uint8_t INT32 = 1 << 1; 39 static constexpr uint8_t FLOAT64 = 1 << 2; 40 static constexpr uint8_t NATIVE = BOOL | INT32 | FLOAT64; 41 static constexpr uint8_t TAGGED = 1 << 3; AddUse(const UseInfo & UseInfo)42 bool AddUse(const UseInfo &UseInfo) 43 { 44 uint8_t oldTag = tag_; 45 tag_ |= UseInfo.tag_; 46 return oldTag != tag_; 47 } UsedAsBool()48 bool UsedAsBool() const 49 { 50 return ((tag_ & BOOL) == BOOL); 51 } UsedAsFloat64()52 bool UsedAsFloat64() const 53 { 54 return ((tag_ & FLOAT64) == FLOAT64); 55 } UsedAsNative()56 bool UsedAsNative() const 57 { 58 return ((tag_ & NATIVE) != 0); 59 } UsedAsTagged()60 bool UsedAsTagged() const 61 { 62 return ((tag_ & TAGGED) != 0); 63 } UnUsed()64 static UseInfo UnUsed() 65 { 66 return UseInfo(UNUSED); 67 } BoolUse()68 static UseInfo BoolUse() 69 { 70 return UseInfo(BOOL); 71 } Int32Use()72 static UseInfo Int32Use() 73 { 74 return UseInfo(INT32); 75 } Float64Use()76 static UseInfo Float64Use() 77 { 78 return UseInfo(FLOAT64); 79 } TaggedUse()80 static UseInfo TaggedUse() 81 { 82 return UseInfo(TAGGED); 83 } 84 private: 85 uint8_t tag_ {0}; 86 }; 87 88 class RangeInfo { 89 public: RangeInfo()90 RangeInfo() {} RangeInfo(int32_t min,int32_t max)91 RangeInfo(int32_t min, int32_t max) 92 { 93 if (min == max) { 94 min_ = max_ = min; 95 } else { 96 auto it = std::upper_bound(rangeBounds_.begin(), rangeBounds_.end(), min); 97 ASSERT(it != rangeBounds_.begin()); 98 it--; 99 min_ = *it; 100 max_ = *std::lower_bound(rangeBounds_.begin(), rangeBounds_.end(), max); 101 } 102 } 103 104 static constexpr int32_t UINT30_MAX = 0x3fffffff; 105 static constexpr int32_t TYPED_ARRAY_ONHEAP_MAX = JSTypedArray::MAX_ONHEAP_LENGTH; 106 static const inline std::vector<int32_t> rangeBounds_ = { INT32_MIN, INT32_MIN + 1, 107 -1, 0, 1, TYPED_ARRAY_ONHEAP_MAX - 1, TYPED_ARRAY_ONHEAP_MAX, TYPED_ARRAY_ONHEAP_MAX + 1, 108 TYPED_ARRAY_ONHEAP_MAX * 3, UINT30_MAX, UINT30_MAX + 1, INT32_MAX - 1, INT32_MAX }; 109 NONE()110 static RangeInfo NONE() 111 { 112 return RangeInfo(INT32_MAX, INT32_MIN); 113 } 114 ANY()115 static RangeInfo ANY() 116 { 117 return RangeInfo(INT32_MIN, INT32_MAX); 118 } 119 GetMin()120 int32_t GetMin() const 121 { 122 return min_; 123 } 124 GetMax()125 int32_t GetMax() const 126 { 127 return max_; 128 } 129 Union(const RangeInfo & rhs)130 RangeInfo Union(const RangeInfo &rhs) const 131 { 132 return RangeInfo(std::min(min_, rhs.min_), std::max(max_, rhs.max_)); 133 } 134 intersection(const RangeInfo & rhs)135 RangeInfo intersection(const RangeInfo &rhs) const 136 { 137 return RangeInfo(std::max(min_, rhs.min_), std::min(max_, rhs.max_)); 138 } 139 MaybeAddOverflow(const RangeInfo & rhs)140 bool MaybeAddOverflow(const RangeInfo &rhs) const 141 { 142 return (rhs.max_ > 0) && (max_ > INT32_MAX - rhs.max_); 143 } 144 MaybeAddUnderflow(const RangeInfo & rhs)145 bool MaybeAddUnderflow(const RangeInfo &rhs) const 146 { 147 return (rhs.min_ < 0) && (min_ < INT32_MIN - rhs.min_); 148 } 149 MaybeAddOverflowOrUnderflow(const RangeInfo & rhs)150 bool MaybeAddOverflowOrUnderflow(const RangeInfo &rhs) const 151 { 152 return MaybeAddOverflow(rhs) || MaybeAddUnderflow(rhs); 153 } 154 155 RangeInfo operator+ (const RangeInfo &rhs) const 156 { 157 int32_t nmax = MaybeAddOverflow(rhs) ? INT32_MAX : max_ + rhs.max_; 158 int32_t nmin = MaybeAddUnderflow(rhs) ? INT32_MIN : min_ + rhs.min_; 159 return RangeInfo(nmin, nmax); 160 } 161 MaybeSubOverflow(const RangeInfo & rhs)162 bool MaybeSubOverflow(const RangeInfo &rhs) const 163 { 164 return (rhs.min_ < 0) && (max_ > INT32_MAX + rhs.min_); 165 } 166 MaybeSubUnderflow(const RangeInfo & rhs)167 bool MaybeSubUnderflow(const RangeInfo &rhs) const 168 { 169 return (rhs.max_ > 0) && (min_ < INT32_MIN + rhs.max_); 170 } 171 MaybeSubOverflowOrUnderflow(const RangeInfo & rhs)172 bool MaybeSubOverflowOrUnderflow(const RangeInfo &rhs) const 173 { 174 return MaybeSubOverflow(rhs) || MaybeSubUnderflow(rhs); 175 } 176 177 RangeInfo operator- (const RangeInfo &rhs) const 178 { 179 int32_t nmax = MaybeSubOverflow(rhs) ? INT32_MAX : max_ - rhs.min_; 180 int32_t nmin = MaybeSubUnderflow(rhs) ? INT32_MIN : min_ - rhs.max_; 181 return RangeInfo(nmin, nmax); 182 } 183 MaybeShrOverflow(const RangeInfo & rhs)184 bool MaybeShrOverflow(const RangeInfo &rhs) const 185 { 186 if (rhs.max_ != rhs.min_) { 187 return true; 188 } 189 return ((static_cast<uint32_t>(rhs.max_) & 0x1f) == 0) && (min_< 0); // 0x1f : shift bits 190 } 191 SHR(const RangeInfo & rhs)192 RangeInfo SHR(const RangeInfo &rhs) const 193 { 194 if (MaybeShrOverflow(rhs)) { 195 // assume no overflow occurs since overflow will lead to deopt 196 return RangeInfo(0, std::max(0, GetMax())); 197 } 198 int32_t shift = rhs.max_ & 0x1f; // 0x1f : shift bits 199 uint32_t tempMin = bit_cast<uint32_t>((max_ >= 0) ? std::max(0, min_) : min_); 200 uint32_t tempMax = bit_cast<uint32_t>((min_ < 0) ? std::min(-1, max_) : max_); 201 int32_t nmin = bit_cast<int32_t>(tempMin >> shift); 202 int32_t nmax = bit_cast<int32_t>(tempMax >> shift); 203 return RangeInfo(nmin, nmax); 204 } 205 ASHR(const RangeInfo & rhs)206 RangeInfo ASHR(const RangeInfo &rhs) const 207 { 208 ASSERT(rhs.max_ == rhs.min_); 209 int32_t shift = rhs.max_ & 0x1f; // 0x1f : shift bits 210 int32_t nmin = min_ >> shift; 211 int32_t nmax = max_ >> shift; 212 return RangeInfo(nmin, nmax); 213 } 214 215 bool operator== (const RangeInfo &rhs) const 216 { 217 return (min_ == rhs.min_) && (max_ == rhs.max_); 218 } 219 220 bool operator!= (const RangeInfo &rhs) const 221 { 222 return (min_ != rhs.min_) || (max_ != rhs.max_); 223 } 224 IsNone()225 bool IsNone() const 226 { 227 return (min_ == INT32_MAX) && (max_ == INT32_MIN); 228 } 229 230 private: 231 int32_t min_ {INT32_MIN}; 232 int32_t max_ {INT32_MAX}; 233 }; 234 } // panda::ecmascript::kungfu 235 #endif // ECMASCRIPT_COMPILER_NUMBER_GATE_INFO_H 236