• 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 };
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