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