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