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