/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ECMASCRIPT_PROPERTY_ATTRIBUTES_H #define ECMASCRIPT_PROPERTY_ATTRIBUTES_H #include "ecmascript/js_tagged_value.h" #include "libpandabase/utils/bit_field.h" namespace panda::ecmascript { class PropertyDescriptor; enum class Representation { NONE, INT, DOUBLE, TAGGED, }; enum class TrackType : uint8_t { NONE = 0x0ULL, INT = 0x1ULL, DOUBLE = 0x1ULL << 1, NUMBER = INT | DOUBLE, TAGGED = 0x1ULL << 2 }; enum class PropertyBoxType { // Meaningful when a property cell does not contain the hole. UNDEFINED, // The PREMONOMORPHIC of property cells. CONSTANT, // Cell has been assigned only once. CONSTANTTYPE, // Cell has been assigned only one type. MUTABLE, // Cell will no longer be tracked as constant. // Meaningful when a property cell contains the hole. UNINITIALIZED = UNDEFINED, // Cell has never been initialized. INVALIDATED = CONSTANT, // Cell has been deleted, invalidated or never existed. }; class PropertyAttributes { public: PropertyAttributes() = default; ~PropertyAttributes() = default; DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyAttributes); DEFAULT_COPY_SEMANTIC(PropertyAttributes); explicit PropertyAttributes(uint32_t v) : value_(v) {} explicit PropertyAttributes(int32_t v) : value_(static_cast(v)) {} explicit PropertyAttributes(JSTaggedValue v) : value_(v.GetInt()) {} explicit PropertyAttributes(const PropertyDescriptor &desc); static constexpr uint32_t DICTIONARY_ORDER_NUM = 20; static constexpr uint32_t OFFSET_BITFIELD_NUM = 10; static constexpr uint32_t REPRESENTATION_NUM = 2; static constexpr uint32_t TRACK_TYPE_NUM = 3; static constexpr uint32_t MAX_CAPACITY_OF_PROPERTIES = (1U << OFFSET_BITFIELD_NUM) - 1; using PropertyMetaDataField = BitField; // 4: property metaData field occupies 4 bits using AttributesField = BitField; // 4: attributes field occupies 4 bits using DefaultAttributesField = BitField; // 3: default attributes field occupies 3 bits using WritableField = BitField; // 1: writable field occupies 1 bits using EnumerableField = WritableField::NextFlag; using ConfigurableField = EnumerableField::NextFlag; using IsAccessorField = ConfigurableField::NextFlag; // 4 using IsInlinedPropsField = PropertyMetaDataField::NextFlag; // 5 using RepresentationField = IsInlinedPropsField::NextField; // 2: 2 bits, 6-8 // fast mode using OffsetField = RepresentationField::NextField; // 18 using TrackTypeField = OffsetField::NextField; // 3: 3 bits static constexpr uint32_t NORMAL_ATTR_BITS = 20; using NormalAttrField = BitField; using SortedIndexField = TrackTypeField::NextField; // 30 using IsConstPropsField = SortedIndexField::NextFlag; // 31 using IsNotHoleField = IsConstPropsField::NextFlag; // 32 // dictionary mode, include global using PropertyBoxTypeField = RepresentationField::NextField; // 2: 2 bits, 9-10 using DictionaryOrderField = PropertyBoxTypeField::NextField; // 30 static constexpr uint32_t BIT_SIZE = 28; static constexpr int INITIAL_PROPERTY_INDEX = 0; inline int GetPropertyMetaData() const { return PropertyMetaDataField::Get(value_); } static PropertyAttributes Default() { return PropertyAttributes(GetDefaultAttributes()); } static PropertyAttributes Default(bool w, bool e, bool c, bool isAccessor = false) { uint32_t value = WritableField::Encode(w) | EnumerableField::Encode(e) | ConfigurableField::Encode(c) | IsAccessorField::Encode(isAccessor); return PropertyAttributes(value); } static PropertyAttributes DefaultAccessor(bool w, bool e, bool c) { uint32_t value = WritableField::Encode(w) | EnumerableField::Encode(e) | ConfigurableField::Encode(c) | IsAccessorField::Encode(true); return PropertyAttributes(value); } inline void SetDefaultAttributes() { AttributesField::Set(DefaultAttributesField::Mask(), &value_); } static inline int GetDefaultAttributes() { return DefaultAttributesField::Mask(); } bool UpdateTrackType(JSTaggedValue value) { TrackType oldType = GetTrackType(); if (oldType == TrackType::TAGGED) { return false; } TrackType newType = TrackType::TAGGED; if (value.IsInt()) { newType = static_cast(static_cast(TrackType::INT) | static_cast(oldType)); } else if (value.IsDouble()) { newType = static_cast(static_cast(TrackType::DOUBLE) | static_cast(oldType)); } if (oldType != newType) { SetTrackType(newType); return true; } return false; } inline bool IsDefaultAttributes() const { return AttributesField::Get(value_) == static_cast(DefaultAttributesField::Mask()); } inline void SetNoneAttributes() { AttributesField::Set(0U, &value_); } inline bool IsNoneAttributes() const { return AttributesField::Get(value_) == 0; } inline void SetWritable(bool flag) { WritableField::Set(flag, &value_); } inline bool IsWritable() const { return WritableField::Get(value_); } inline void SetEnumerable(bool flag) { EnumerableField::Set(flag, &value_); } inline bool IsEnumerable() const { return EnumerableField::Get(value_); } inline void SetConfigurable(bool flag) { ConfigurableField::Set(flag, &value_); } inline bool IsConfigurable() const { return ConfigurableField::Get(value_); } inline void SetIsAccessor(bool flag) { IsAccessorField::Set(flag, &value_); } inline bool IsAccessor() const { return IsAccessorField::Get(value_); } inline void SetIsInlinedProps(bool flag) { IsInlinedPropsField::Set(flag, &value_); } inline bool IsInlinedProps() const { return IsInlinedPropsField::Get(value_); } inline void SetIsConstProps(bool flag) { IsConstPropsField::Set(flag, &value_); } inline bool IsConstProps() const { return IsConstPropsField::Get(value_); } inline void SetIsNotHole(bool flag) { IsNotHoleField::Set(flag, &value_); } inline bool IsNotHole() const { return IsNotHoleField::Get(value_); } inline bool IsTaggedRep() const { return !IsDoubleRep() && !IsIntRep(); } inline bool IsDoubleRep() const { auto rep = GetRepresentation(); return rep == Representation::DOUBLE; } inline bool IsIntRep() const { auto rep = GetRepresentation(); return rep == Representation::INT; } inline void SetRepresentation(Representation representation) { RepresentationField::Set(representation, &value_); } inline Representation GetRepresentation() const { return RepresentationField::Get(value_); } inline TrackType GetTrackType() const { return TrackTypeField::Get(value_); } inline void SetTrackType(TrackType type) { TrackTypeField::Set(type, &value_); } inline void SetDictionaryOrder(uint32_t order) { DictionaryOrderField::Set(order, &value_); } inline uint32_t GetDictionaryOrder() const { return DictionaryOrderField::Get(value_); } inline void SetOffset(uint32_t offset) { OffsetField::Set(offset, &value_); } inline uint32_t GetOffset() const { return OffsetField::Get(value_); } inline void SetSortedIndex(uint32_t sortedIndex) { SortedIndexField::Set(sortedIndex, &value_); } inline uint32_t GetSortedIndex() const { return SortedIndexField::Get(value_); } inline void SetNormalAttr(uint32_t normalAttr) { NormalAttrField::Set(normalAttr, &value_); } inline uint32_t GetNormalAttr() const { return NormalAttrField::Get(value_); } inline JSTaggedValue GetNormalTagged() const { return JSTaggedValue(static_cast(GetNormalAttr())); } inline uint32_t GetValue() const { return value_; } inline void SetBoxType(PropertyBoxType cellType) { PropertyBoxTypeField::Set(cellType, &value_); } inline PropertyBoxType GetBoxType() const { return PropertyBoxTypeField::Get(value_); } inline static bool IsValidIndex(int index) { return DictionaryOrderField::IsValid(index); } inline JSTaggedValue GetTaggedValue() const { return JSTaggedValue(static_cast(value_)); } private: uint32_t value_{0}; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_PROPERTY_ATTRIBUTES_H