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