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