1 /*
2  * Copyright (c) 2021-2024 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_JSSYMBOL_H
17 #define ECMASCRIPT_JSSYMBOL_H
18 
19 #include "ecmascript/ecma_string.h"
20 #include "ecmascript/js_object.h"
21 #include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
22 
23 namespace panda {
24 namespace ecmascript {
25 using ProfileType = pgo::ProfileType;
26 
27 class JSSymbol : public TaggedObject {
28 public:
29     static constexpr uint32_t IS_PRIVATE = 1U << 0U;
30     static constexpr uint32_t IS_WELL_KNOWN_SYMBOL = 1U << 1U;
31     static constexpr uint32_t IS_IN_PUBLIC_SYMBOL_TABLE = 1U << 2U;
32     static constexpr uint32_t IS_INTERESTING_SYMBOL = 1U << 3U;
33     static constexpr uint32_t IS_PRIVATE_NAME = 1U << 4U;
34     static constexpr uint32_t IS_PRIVATE_BRAND = 1U << 5U;
35     static constexpr uint32_t HAS_ID = 1U << 6U;
36 
37     static constexpr int SYMBOL_HAS_INSTANCE_TYPE = 0;
38     static constexpr int SYMBOL_TO_PRIMITIVE_TYPE = 1;
39     static constexpr int SYMBOL_DEFAULT_TYPE = 2;
40 
41     static constexpr const uint32_t LINEAR_X = 1103515245U;
42     static constexpr const uint32_t LINEAR_Y = 12345U;
43     static constexpr const uint32_t LINEAR_SEED = 987654321U;
44 
45     // 48: high 16 bits need to be double encoded as a valid number tagged value
46     static constexpr size_t SYMBOL_ID_BITFIELD_NUM = 48;
47     static constexpr size_t ABC_ID_OFFSET_BIT = SYMBOL_ID_BITFIELD_NUM - ProfileType::ABC_ID_BITFIELD_NUM;
48     static constexpr size_t LITERAL_ID_BITFIELD_NUM = 16;
49     static constexpr size_t LITERAL_ID_OFFSET_BIT = ABC_ID_OFFSET_BIT - LITERAL_ID_BITFIELD_NUM;
50 
51 public:
52     CAST_CHECK(JSSymbol, IsSymbol);
53 
ComputeHash()54     static inline uint32_t ComputeHash()
55     {
56         uint32_t hashSeed = static_cast<uint32_t>(LINEAR_SEED + std::time(nullptr));
57         uint32_t hash = hashSeed * LINEAR_X + LINEAR_Y;
58         return hash;
59     }
60 
HasId() const61     bool HasId() const
62     {
63         return (GetFlags() & HAS_ID) != 0U;
64     }
65 
SetHasId()66     void SetHasId()
67     {
68         SetFlags(GetFlags() | HAS_ID);
69     }
70 
IsPrivate() const71     bool IsPrivate() const
72     {
73         return (GetFlags() & IS_PRIVATE) != 0U;
74     }
75 
SetPrivate()76     void SetPrivate()
77     {
78         SetFlags(GetFlags() | IS_PRIVATE);
79     }
80 
IsWellKnownSymbol() const81     bool IsWellKnownSymbol() const
82     {
83         return (GetFlags() & IS_WELL_KNOWN_SYMBOL) != 0U;
84     }
85 
SetWellKnownSymbol()86     void SetWellKnownSymbol()
87     {
88         SetFlags(GetFlags() | IS_WELL_KNOWN_SYMBOL);
89     }
90 
IsInPublicSymbolTable() const91     bool IsInPublicSymbolTable() const
92     {
93         return (GetFlags() & IS_IN_PUBLIC_SYMBOL_TABLE) != 0U;
94     }
95 
SetInPublicSymbolTable()96     void SetInPublicSymbolTable()
97     {
98         SetFlags(GetFlags() | IS_IN_PUBLIC_SYMBOL_TABLE);
99     }
100 
IsInterestingSymbol() const101     bool IsInterestingSymbol() const
102     {
103         return (GetFlags() & IS_INTERESTING_SYMBOL) != 0U;
104     }
105 
SetInterestingSymbol()106     void SetInterestingSymbol()
107     {
108         SetFlags(GetFlags() | IS_INTERESTING_SYMBOL);
109     }
110 
IsPrivateNameSymbol() const111     bool IsPrivateNameSymbol() const
112     {
113         return (GetFlags() & IS_PRIVATE_NAME) != 0U;
114     }
115 
SetPrivateNameSymbol()116     void SetPrivateNameSymbol()
117     {
118         SetFlags(GetFlags() | IS_PRIVATE_NAME);
119     }
120 
Equal(const JSSymbol &src, const JSSymbol &dst)121     static bool Equal(const JSSymbol &src, const JSSymbol &dst)
122     {
123         if (src.GetFlags() != dst.GetFlags()) {
124             return false;
125         }
126         EcmaString *srcString = EcmaString::Cast(src.GetDescription().GetTaggedObject());
127         EcmaString *dstString = EcmaString::Cast(dst.GetDescription().GetTaggedObject());
128         return EcmaStringAccessor::StringsAreEqual(srcString, dstString);
129     }
130 
GetPrivateId()131     uint64_t GetPrivateId()
132     {
133         return GetId();
134     }
135 
SetPrivateId(uint64_t id)136     void SetPrivateId(uint64_t id)
137     {
138         SetHasId();
139         SetId(id);
140     }
141 
GeneratePrivateId(uint64_t abcId, uint64_t literalId, uint64_t slotIndex)142     static uint64_t GeneratePrivateId(uint64_t abcId, uint64_t literalId, uint64_t slotIndex)
143     {
144         return JSTaggedValueInternals::DOUBLE_ENCODE_OFFSET | (abcId << ABC_ID_OFFSET_BIT) |
145                (literalId << LITERAL_ID_OFFSET_BIT) | slotIndex;
146     }
147 
GetSlotIndex(uint64_t id)148     static uint64_t GetSlotIndex(uint64_t id)
149     {
150         uint64_t mask = (1ULL << LITERAL_ID_OFFSET_BIT) - 1;
151         return id & mask;
152     }
153 
GetLiteralId(uint64_t id)154     static uint64_t GetLiteralId(uint64_t id)
155     {
156         uint64_t mask = (1ULL << LITERAL_ID_BITFIELD_NUM) - 1;
157         return (id >> LITERAL_ID_OFFSET_BIT) & mask;
158     }
159 
GetAbcId(uint64_t id)160     static uint64_t GetAbcId(uint64_t id)
161     {
162         uint64_t mask = (1ULL << ProfileType::ABC_ID_BITFIELD_NUM) - 1;
163         return (id >> ABC_ID_OFFSET_BIT) & mask;
164     }
165 
166 public:
167     static constexpr size_t DESCRIPTION_OFFSET = TaggedObjectSize();
168     ACCESSORS(Description, DESCRIPTION_OFFSET, HASHFIELD_OFFSET)
169     ACCESSORS_PRIMITIVE_FIELD(HashField, uint32_t, HASHFIELD_OFFSET, FLAGS_OFFSET)
170     ACCESSORS_PRIMITIVE_FIELD(Flags, uint32_t, FLAGS_OFFSET, ID_OFFSET)
171     ACCESSORS_PRIMITIVE_FIELD(Id, uint64_t, ID_OFFSET, LAST_OFFSET)
172     DEFINE_ALIGN_SIZE(LAST_OFFSET);
173 
174     DECL_DUMP()
175 
176     DECL_VISIT_OBJECT(DESCRIPTION_OFFSET, HASHFIELD_OFFSET)
177 };
178 }  // namespace ecmascript
179 }  // namespace panda
180 #endif  // ECMASCRIPT_NAME_H
181