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