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_PROPERTY_ATTRIBUTES_H 17 #define ECMASCRIPT_PROPERTY_ATTRIBUTES_H 18 19 #include "ecmascript/js_tagged_value.h" 20 21 #include "libpandabase/utils/bit_field.h" 22 23 namespace panda::ecmascript { 24 class PropertyDescriptor; 25 26 enum class Representation { 27 NONE, 28 INT, 29 DOUBLE, 30 TAGGED, 31 }; 32 33 enum class TrackType : uint8_t { 34 NONE = 0x0ULL, 35 INT = 0x1ULL, 36 DOUBLE = 0x1ULL << 1, 37 NUMBER = INT | DOUBLE, 38 TAGGED = 0x1ULL << 2 39 }; 40 41 enum class PropertyBoxType { 42 // Meaningful when a property cell does not contain the hole. 43 UNDEFINED, // The PREMONOMORPHIC of property cells. 44 CONSTANT, // Cell has been assigned only once. 45 CONSTANTTYPE, // Cell has been assigned only one type. 46 MUTABLE, // Cell will no longer be tracked as constant. 47 48 // Meaningful when a property cell contains the hole. 49 UNINITIALIZED = UNDEFINED, // Cell has never been initialized. 50 INVALIDATED = CONSTANT, // Cell has been deleted, invalidated or never existed. 51 }; 52 53 class PropertyAttributes { 54 public: 55 PropertyAttributes() = default; 56 ~PropertyAttributes() = default; 57 58 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyAttributes); 59 DEFAULT_COPY_SEMANTIC(PropertyAttributes); 60 PropertyAttributes(uint32_t v)61 explicit PropertyAttributes(uint32_t v) : value_(v) {} PropertyAttributes(int32_t v)62 explicit PropertyAttributes(int32_t v) : value_(static_cast<uint32_t>(v)) {} PropertyAttributes(JSTaggedValue v)63 explicit PropertyAttributes(JSTaggedValue v) : value_(v.GetInt()) {} 64 explicit PropertyAttributes(const PropertyDescriptor &desc); 65 66 static constexpr uint32_t DICTIONARY_ORDER_NUM = 20; 67 static constexpr uint32_t OFFSET_BITFIELD_NUM = 10; 68 static constexpr uint32_t REPRESENTATION_NUM = 2; 69 static constexpr uint32_t TRACK_TYPE_NUM = 3; 70 static constexpr uint32_t MAX_CAPACITY_OF_PROPERTIES = (1U << OFFSET_BITFIELD_NUM) - 1; 71 72 using PropertyMetaDataField = BitField<int, 0, 4>; // 4: property metaData field occupies 4 bits 73 using AttributesField = BitField<int, 0, 4>; // 4: attributes field occupies 4 bits 74 using DefaultAttributesField = BitField<int, 0, 3>; // 3: default attributes field occupies 3 bits 75 using WritableField = BitField<bool, 0, 1>; // 1: writable field occupies 1 bits 76 using EnumerableField = WritableField::NextFlag; 77 using ConfigurableField = EnumerableField::NextFlag; 78 using IsAccessorField = ConfigurableField::NextFlag; // 4 79 80 using IsInlinedPropsField = PropertyMetaDataField::NextFlag; // 5 81 using RepresentationField = IsInlinedPropsField::NextField<Representation, REPRESENTATION_NUM>; // 2: 2 bits, 6-8 82 // fast mode 83 using OffsetField = RepresentationField::NextField<uint32_t, OFFSET_BITFIELD_NUM>; // 18 84 using TrackTypeField = OffsetField::NextField<TrackType, TRACK_TYPE_NUM>; // 3: 3 bits 85 86 static constexpr uint32_t NORMAL_ATTR_BITS = 20; 87 using NormalAttrField = BitField<int, 0, NORMAL_ATTR_BITS>; 88 using SortedIndexField = TrackTypeField::NextField<uint32_t, OFFSET_BITFIELD_NUM>; // 30 89 using IsConstPropsField = SortedIndexField::NextFlag; // 31 90 using IsNotHoleField = IsConstPropsField::NextFlag; // 32 91 // dictionary mode, include global 92 using PropertyBoxTypeField = RepresentationField::NextField<PropertyBoxType, 2>; // 2: 2 bits, 9-10 93 using DictionaryOrderField = PropertyBoxTypeField::NextField<uint32_t, DICTIONARY_ORDER_NUM>; // 30 94 95 static constexpr uint32_t BIT_SIZE = 28; 96 static constexpr int INITIAL_PROPERTY_INDEX = 0; 97 GetPropertyMetaData()98 inline int GetPropertyMetaData() const 99 { 100 return PropertyMetaDataField::Get(value_); 101 } 102 Default()103 static PropertyAttributes Default() 104 { 105 return PropertyAttributes(GetDefaultAttributes()); 106 } 107 108 static PropertyAttributes Default(bool w, bool e, bool c, bool isAccessor = false) 109 { 110 uint32_t value = WritableField::Encode(w) | EnumerableField::Encode(e) | ConfigurableField::Encode(c) | 111 IsAccessorField::Encode(isAccessor); 112 return PropertyAttributes(value); 113 } 114 DefaultAccessor(bool w,bool e,bool c)115 static PropertyAttributes DefaultAccessor(bool w, bool e, bool c) 116 { 117 uint32_t value = WritableField::Encode(w) | EnumerableField::Encode(e) | ConfigurableField::Encode(c) | 118 IsAccessorField::Encode(true); 119 return PropertyAttributes(value); 120 } 121 SetDefaultAttributes()122 inline void SetDefaultAttributes() 123 { 124 AttributesField::Set<uint32_t>(DefaultAttributesField::Mask(), &value_); 125 } 126 GetDefaultAttributes()127 static inline int GetDefaultAttributes() 128 { 129 return DefaultAttributesField::Mask(); 130 } 131 UpdateTrackType(JSTaggedValue value)132 bool UpdateTrackType(JSTaggedValue value) 133 { 134 TrackType oldType = GetTrackType(); 135 if (oldType == TrackType::TAGGED) { 136 return false; 137 } 138 139 TrackType newType = TrackType::TAGGED; 140 if (value.IsInt()) { 141 newType = static_cast<TrackType>(static_cast<uint8_t>(TrackType::INT) | static_cast<uint8_t>(oldType)); 142 } else if (value.IsDouble()) { 143 newType = static_cast<TrackType>(static_cast<uint8_t>(TrackType::DOUBLE) | static_cast<uint8_t>(oldType)); 144 } 145 146 if (oldType != newType) { 147 SetTrackType(newType); 148 return true; 149 } 150 return false; 151 } 152 IsDefaultAttributes()153 inline bool IsDefaultAttributes() const 154 { 155 return AttributesField::Get(value_) == static_cast<int>(DefaultAttributesField::Mask()); 156 } 157 SetNoneAttributes()158 inline void SetNoneAttributes() 159 { 160 AttributesField::Set<uint32_t>(0U, &value_); 161 } 162 IsNoneAttributes()163 inline bool IsNoneAttributes() const 164 { 165 return AttributesField::Get(value_) == 0; 166 } 167 SetWritable(bool flag)168 inline void SetWritable(bool flag) 169 { 170 WritableField::Set<uint32_t>(flag, &value_); 171 } IsWritable()172 inline bool IsWritable() const 173 { 174 return WritableField::Get(value_); 175 } SetEnumerable(bool flag)176 inline void SetEnumerable(bool flag) 177 { 178 EnumerableField::Set<uint32_t>(flag, &value_); 179 } IsEnumerable()180 inline bool IsEnumerable() const 181 { 182 return EnumerableField::Get(value_); 183 } SetConfigurable(bool flag)184 inline void SetConfigurable(bool flag) 185 { 186 ConfigurableField::Set<uint32_t>(flag, &value_); 187 } IsConfigurable()188 inline bool IsConfigurable() const 189 { 190 return ConfigurableField::Get(value_); 191 } 192 SetIsAccessor(bool flag)193 inline void SetIsAccessor(bool flag) 194 { 195 IsAccessorField::Set<uint32_t>(flag, &value_); 196 } 197 IsAccessor()198 inline bool IsAccessor() const 199 { 200 return IsAccessorField::Get(value_); 201 } 202 SetIsInlinedProps(bool flag)203 inline void SetIsInlinedProps(bool flag) 204 { 205 IsInlinedPropsField::Set<uint32_t>(flag, &value_); 206 } 207 IsInlinedProps()208 inline bool IsInlinedProps() const 209 { 210 return IsInlinedPropsField::Get(value_); 211 } 212 SetIsConstProps(bool flag)213 inline void SetIsConstProps(bool flag) 214 { 215 IsConstPropsField::Set<uint32_t>(flag, &value_); 216 } 217 IsConstProps()218 inline bool IsConstProps() const 219 { 220 return IsConstPropsField::Get(value_); 221 } 222 SetIsNotHole(bool flag)223 inline void SetIsNotHole(bool flag) 224 { 225 IsNotHoleField::Set<uint32_t>(flag, &value_); 226 } 227 IsNotHole()228 inline bool IsNotHole() const 229 { 230 return IsNotHoleField::Get(value_); 231 } 232 IsTaggedRep()233 inline bool IsTaggedRep() const 234 { 235 return !IsDoubleRep() && !IsIntRep(); 236 } 237 IsDoubleRep()238 inline bool IsDoubleRep() const 239 { 240 auto rep = GetRepresentation(); 241 return rep == Representation::DOUBLE; 242 } 243 IsIntRep()244 inline bool IsIntRep() const 245 { 246 auto rep = GetRepresentation(); 247 return rep == Representation::INT; 248 } 249 SetRepresentation(Representation representation)250 inline void SetRepresentation(Representation representation) 251 { 252 RepresentationField::Set<uint32_t>(representation, &value_); 253 } 254 GetRepresentation()255 inline Representation GetRepresentation() const 256 { 257 return RepresentationField::Get(value_); 258 } 259 GetTrackType()260 inline TrackType GetTrackType() const 261 { 262 return TrackTypeField::Get(value_); 263 } 264 SetTrackType(TrackType type)265 inline void SetTrackType(TrackType type) 266 { 267 TrackTypeField::Set(type, &value_); 268 } 269 SetDictionaryOrder(uint32_t order)270 inline void SetDictionaryOrder(uint32_t order) 271 { 272 DictionaryOrderField::Set<uint32_t>(order, &value_); 273 } GetDictionaryOrder()274 inline uint32_t GetDictionaryOrder() const 275 { 276 return DictionaryOrderField::Get(value_); 277 } 278 SetOffset(uint32_t offset)279 inline void SetOffset(uint32_t offset) 280 { 281 OffsetField::Set<uint32_t>(offset, &value_); 282 } GetOffset()283 inline uint32_t GetOffset() const 284 { 285 return OffsetField::Get(value_); 286 } 287 SetSortedIndex(uint32_t sortedIndex)288 inline void SetSortedIndex(uint32_t sortedIndex) 289 { 290 SortedIndexField::Set<uint32_t>(sortedIndex, &value_); 291 } GetSortedIndex()292 inline uint32_t GetSortedIndex() const 293 { 294 return SortedIndexField::Get(value_); 295 } 296 SetNormalAttr(uint32_t normalAttr)297 inline void SetNormalAttr(uint32_t normalAttr) 298 { 299 NormalAttrField::Set<uint32_t>(normalAttr, &value_); 300 } 301 GetNormalAttr()302 inline uint32_t GetNormalAttr() const 303 { 304 return NormalAttrField::Get(value_); 305 } 306 GetNormalTagged()307 inline JSTaggedValue GetNormalTagged() const 308 { 309 return JSTaggedValue(static_cast<int>(GetNormalAttr())); 310 } 311 GetValue()312 inline uint32_t GetValue() const 313 { 314 return value_; 315 } 316 SetBoxType(PropertyBoxType cellType)317 inline void SetBoxType(PropertyBoxType cellType) 318 { 319 PropertyBoxTypeField::Set<uint32_t>(cellType, &value_); 320 } 321 GetBoxType()322 inline PropertyBoxType GetBoxType() const 323 { 324 return PropertyBoxTypeField::Get(value_); 325 } 326 IsValidIndex(int index)327 inline static bool IsValidIndex(int index) 328 { 329 return DictionaryOrderField::IsValid(index); 330 } 331 GetTaggedValue()332 inline JSTaggedValue GetTaggedValue() const 333 { 334 return JSTaggedValue(static_cast<int>(value_)); 335 } 336 337 private: 338 uint32_t value_{0}; 339 }; 340 } // namespace panda::ecmascript 341 #endif // ECMASCRIPT_PROPERTY_ATTRIBUTES_H 342