• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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