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