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