• 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_TAGGED_DICTIONARY_H
17 #define ECMASCRIPT_TAGGED_DICTIONARY_H
18 
19 #include "ecmascript/js_tagged_value-inl.h"
20 #include "ecmascript/platform/mutex.h"
21 #include "ecmascript/tagged_array-inl.h"
22 #include "ecmascript/tagged_hash_table.h"
23 
24 namespace panda::ecmascript {
25 class NameDictionary : public OrderTaggedHashTable<NameDictionary> {
26 public:
27     using OrderHashTableT = OrderTaggedHashTable<NameDictionary>;
GetKeyIndex(int entry)28     inline static int GetKeyIndex(int entry)
29     {
30         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX;
31     }
GetValueIndex(int entry)32     inline static int GetValueIndex(int entry)
33     {
34         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX;
35     }
GetEntryIndex(int entry)36     inline static int GetEntryIndex(int entry)
37     {
38         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize();
39     }
GetEntrySize()40     inline static int GetEntrySize()
41     {
42         return ENTRY_SIZE;
43     }
44     static int PUBLIC_API Hash(const JSThread *thread, const JSTaggedValue &key);
45     static int Hash(const uint8_t* str, int strSize);
46 
47     static bool PUBLIC_API IsMatch([[maybe_unused]] const JSThread *thread, const JSTaggedValue &key,
48         const JSTaggedValue &other);
49     static bool IsMatch(const uint8_t* str, int size, const JSTaggedValue &other);
50 
51     static JSHandle<NameDictionary> Create(const JSThread *thread,
52         int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER);
53     static JSHandle<NameDictionary> PUBLIC_API CreateInSharedHeap(const JSThread *thread,
54         int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER);
55     // Returns the property metaData for the property at entry.
56     PropertyAttributes PUBLIC_API GetAttributes(const JSThread *thread, int entry) const;
57     void PUBLIC_API SetAttributes(const JSThread *thread, int entry, const PropertyAttributes &metaData);
58     void PUBLIC_API SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value,
59                              const PropertyAttributes &metaData);
60     void UpdateValueAndAttributes(const JSThread *thread, int entry, const JSTaggedValue &value,
61                                   const PropertyAttributes &metaData);
62     void PUBLIC_API UpdateValue(const JSThread *thread, int entry, const JSTaggedValue &value);
63     void UpdateAttributes(int entry, const PropertyAttributes &metaData);
64     void UpdateAllAttributesToNoWitable(const JSThread *thread);
65     void ClearEntry(const JSThread *thread, int entry);
66     void GetAllKeys(const JSThread *thread, int offset, TaggedArray *keyArray) const;
67     void GetAllKeysByFilter(const JSThread *thread, uint32_t &keyArrayEffectivelength,
68         TaggedArray *keyArray, uint32_t filter) const;
69     std::pair<uint32_t, uint32_t> GetNumOfEnumKeys(const JSThread *thread) const;
70     void GetAllEnumKeys(JSThread *thread, int offset, JSHandle<TaggedArray> keyArray, uint32_t *keys,
71                         JSHandle<TaggedQueue> shadowQueue, int32_t lastLength) const;
72     void GetAllEnumKeys(JSThread *thread, int offset, JSHandle<TaggedArray> keyArray, uint32_t *keys) const;
CompHandleKey(const std::pair<JSHandle<JSTaggedValue>,PropertyAttributes> & a,const std::pair<JSHandle<JSTaggedValue>,PropertyAttributes> & b)73     static inline bool CompHandleKey(const std::pair<JSHandle<JSTaggedValue>, PropertyAttributes> &a,
74                                      const std::pair<JSHandle<JSTaggedValue>, PropertyAttributes> &b)
75     {
76         return a.second.GetDictionaryOrder() < b.second.GetDictionaryOrder();
77     }
CompKey(const std::pair<JSTaggedValue,PropertyAttributes> & a,const std::pair<JSTaggedValue,PropertyAttributes> & b)78     static inline bool CompKey(const std::pair<JSTaggedValue, PropertyAttributes> &a,
79                                const std::pair<JSTaggedValue, PropertyAttributes> &b)
80     {
81         return a.second.GetDictionaryOrder() < b.second.GetDictionaryOrder();
82     }
CompIndex(const PropertyAttributes & a,const PropertyAttributes & b)83     static inline bool CompIndex(const PropertyAttributes &a,
84                                  const PropertyAttributes &b)
85     {
86         return a.GetDictionaryOrder() < b.GetDictionaryOrder();
87     }
88     void Dump(const JSThread *thread, std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR;
Dump(const JSThread * thread)89     void Dump(const JSThread *thread) const DUMP_API_ATTR
90     {
91         Dump(thread, std::cout);
92     }
93     void DumpForSnapshot(const JSThread *thread, std::vector<Reference> &vec) const;
94 
95     static constexpr int ENTRY_KEY_INDEX = 0;
96     static constexpr int ENTRY_VALUE_INDEX = 1;
97     static constexpr int ENTRY_DETAILS_INDEX = 2;
98     static constexpr int ENTRY_SIZE = 3;
99 };
100 
101 class NumberDictionary : public OrderTaggedHashTable<NumberDictionary> {
102 public:
103     using OrderHashTableT = OrderTaggedHashTable<NumberDictionary>;
GetKeyIndex(int entry)104     inline static int GetKeyIndex(int entry)
105     {
106         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX;
107     }
GetValueIndex(int entry)108     inline static int GetValueIndex(int entry)
109     {
110         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX;
111     }
GetEntryIndex(int entry)112     inline static int GetEntryIndex(int entry)
113     {
114         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize();
115     }
GetEntrySize()116     inline static int GetEntrySize()
117     {
118         return ENTRY_SIZE;
119     }
120     static int PUBLIC_API Hash([[maybe_unused]] const JSThread *thread, const JSTaggedValue &key);
121     static bool PUBLIC_API IsMatch([[maybe_unused]] const JSThread *thread, const JSTaggedValue &key,
122         const JSTaggedValue &other);
123     static JSHandle<NumberDictionary> Create(const JSThread *thread,
124                                     int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER);
125     static JSHandle<NumberDictionary> CreateInSharedHeap(
126         const JSThread *thread, int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER);
127     // Returns the property metaData for the property at entry.
128     PropertyAttributes PUBLIC_API GetAttributes(const JSThread *thread, int entry) const;
129     void SetAttributes(const JSThread *thread, int entry, const PropertyAttributes &metaData);
130     void SetEntry([[maybe_unused]] const JSThread *thread, int entry, const JSTaggedValue &key,
131                   const JSTaggedValue &value, const PropertyAttributes &metaData);
132     void UpdateValueAndAttributes(const JSThread *thread, int entry, const JSTaggedValue &value,
133                                   const PropertyAttributes &metaData);
134     void PUBLIC_API UpdateValue(const JSThread *thread, int entry, const JSTaggedValue &value);
135     void UpdateAttributes(int entry, const PropertyAttributes &metaData);
136     void ClearEntry(const JSThread *thread, int entry);
137 
138     static void GetAllKeys(const JSThread *thread, const JSHandle<NumberDictionary> &obj, int offset,
139                            const JSHandle<TaggedArray> &keyArray);
140     static void GetAllKeysByFilter(const JSThread *thread, const JSHandle<NumberDictionary> &obj,
141         uint32_t &keyArrayEffectivelength, const JSHandle<TaggedArray> &keyArray, uint32_t filter);
142     static void GetAllEnumKeys(JSThread *thread, const JSHandle<NumberDictionary> &obj, int offset,
143                                const JSHandle<TaggedArray> &keyArray, uint32_t *keys, int32_t lastLength = -1);
CompKey(const JSTaggedValue & a,const JSTaggedValue & b)144     static inline bool CompKey(const JSTaggedValue &a, const JSTaggedValue &b)
145     {
146         ASSERT(a.IsNumber() && b.IsNumber());
147         return a.GetNumber() < b.GetNumber();
148     }
149     void Dump(const JSThread *thread, std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR;
Dump(const JSThread * thread)150     void Dump(const JSThread *thread) const DUMP_API_ATTR
151     {
152         Dump(thread, std::cout);
153     }
154     void DumpForSnapshot(const JSThread *thread, std::vector<Reference> &vec) const;
155 
156     static constexpr int ENTRY_KEY_INDEX = 0;
157     static constexpr int ENTRY_VALUE_INDEX = 1;
158     static constexpr int ENTRY_DETAILS_INDEX = 2;
159     static constexpr int ENTRY_SIZE = 3;
160 };
161 
162 class PointerToIndexDictionary : public OrderTaggedHashTable<PointerToIndexDictionary> {
163 public:
164     using OrderHashTableT = OrderTaggedHashTable<PointerToIndexDictionary>;
GetKeyIndex(int entry)165     inline static int GetKeyIndex(int entry)
166     {
167         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX;
168     }
169 
GetValueIndex(int entry)170     inline static int GetValueIndex(int entry)
171     {
172         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX;
173     }
174 
GetEntryIndex(int entry)175     inline static int GetEntryIndex(int entry)
176     {
177         return OrderHashTableT::TABLE_HEADER_SIZE + entry * GetEntrySize();
178     }
179 
GetEntrySize()180     inline static int GetEntrySize()
181     {
182         return ENTRY_SIZE;
183     }
184 
SetEntry(const JSThread * thread,int entry,const JSTaggedValue & key,const JSTaggedValue & value)185     inline void SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value)
186     {
187         SetKey(thread, entry, key);
188         SetValue(thread, entry, value);
189     }
190 
Hash(const JSThread * thread,const JSTaggedValue & key)191     static int32_t Hash([[maybe_unused]] const JSThread *thread, const JSTaggedValue &key)
192     {
193         return static_cast<int32_t>(key.GetRawData());
194     }
195 
IsMatch(const JSThread * thread,const JSTaggedValue & key,const JSTaggedValue & other)196     static bool IsMatch([[maybe_unused]] const JSThread *thread, const JSTaggedValue &key, const JSTaggedValue &other)
197     {
198         return key == other;
199     }
200     static JSHandle<PointerToIndexDictionary> Create(const JSThread *thread,
201                                         int numberOfElements = OrderHashTableT::DEFAULT_ELEMENTS_NUMBER);
202     static JSHandle<PointerToIndexDictionary> PutIfAbsent(
203                                         const JSThread *thread, const JSHandle<PointerToIndexDictionary> &dictionary,
204                                         const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value);
205 
206     // DECL_DUMP()
207 
208     static constexpr int ENTRY_KEY_INDEX = 0;
209     static constexpr int ENTRY_VALUE_INDEX = 1;
210     static constexpr int ENTRY_SIZE = 2;
211 };
212 
213 class FunctionProtoTransitionTable {
214 public:
215     explicit FunctionProtoTransitionTable(const JSThread *thread);
216     virtual ~FunctionProtoTransitionTable();
217 
218     void Iterate(RootVisitor &v);
219 
220     void InsertTransitionItem(const JSThread *thread,
221                               JSHandle<JSTaggedValue> ihc,
222                               JSHandle<JSTaggedValue> baseIhc,
223                               JSHandle<JSTaggedValue> transIhc,
224                               JSHandle<JSTaggedValue> transPhc);
225 
226     std::pair<JSTaggedValue, JSTaggedValue> FindTransitionByHClass(const JSThread *thread,
227                                                                    JSHandle<JSTaggedValue> ihc,
228                                                                    JSHandle<JSTaggedValue> baseIhc) const;
229 
230     bool TryInsertFakeParentItem(JSTaggedType child, JSTaggedType parent);
231     JSTaggedType GetFakeParent(JSTaggedType child);
232 
GetProtoTransitionTable()233     JSTaggedValue GetProtoTransitionTable() const
234     {
235         return protoTransitionTable_;
236     }
237 
238     void UpdateProtoTransitionTable(const JSThread *thread, JSHandle<PointerToIndexDictionary> map);
239 
240     class ProtoArray : public TaggedArray {
241     public:
242         CAST_CHECK(ProtoArray, IsTaggedArray);
243 
244         static JSHandle<ProtoArray> Create(const JSThread *thread);
245         void SetEntry(const JSThread *thread, uint32_t index, JSTaggedValue key, JSTaggedValue transIhc,
246                       JSTaggedValue transPhc);
247         JSTaggedValue GetKey(const JSThread *thread, uint32_t index) const;
248         std::pair<JSTaggedValue, JSTaggedValue> GetTransition(const JSThread *thread, uint32_t index) const;
249         int32_t FindEntry(const JSThread *thread, JSTaggedValue key) const;
250         std::pair<JSTaggedValue, JSTaggedValue> FindTransition(const JSThread *thread, JSTaggedValue key) const;
251         static bool GetEntry(JSHandle<JSHClass> hclass);
252 
253     private:
254         static constexpr uint32_t ENTRY_NUMBER = 2;
255         static constexpr uint32_t INIT_ENTRY_INDEX = 0;
256         static constexpr uint32_t CLONED_ENTRY_INDEX = 1;
257 
258         static constexpr uint32_t ENTRY_SIZE = 3;
259         static constexpr uint32_t KEY_INDEX = 0;
260         static constexpr uint32_t TRANS_IHC_INDEX = 1;
261         static constexpr uint32_t TRANS_PHC_INDEX = 2;
262     };
263 
264 private:
265     static constexpr uint32_t DEFAULT_FIRST_LEVEL_SIZE = 2;
266     // second level table:
267     // <PointerToIndexDictionary(n):
268     //      [ihc,
269     //          <ProtoArray(2):
270     //              [base.ihc,
271     //                  (trans_ihc, trans_phc)
272     //              ]
273     //              [base.ihc(cloned),
274     //                  (trans_ihc, trans_phc)
275     //              ]
276     //          >
277     //      ]
278     //      ...
279     //  >
280     JSTaggedValue protoTransitionTable_ {JSTaggedValue::Hole()};
281     // hclasses after set prototype maps to hclasses before set prototype
282     CUnorderedMap<JSTaggedType, JSTaggedType> fakeParentMap_ {};
283     // reverse fakeParentMap_
284     CUnorderedMap<JSTaggedType, JSTaggedType> fakeChildMap_ {};
285     Mutex fakeParentMutex_;
286 };
287 }  // namespace panda::ecmascript
288 #endif  // ECMASCRIPT_NEW_DICTIONARY_H
289