• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "ecmascript/tagged_dictionary.h"
17 
18 #include "ecmascript/tagged_hash_table.h"
19 
20 namespace panda::ecmascript {
Hash(const JSTaggedValue & key)21 int NameDictionary::Hash(const JSTaggedValue &key)
22 {
23     if (key.IsHeapObject()) {
24         JSTaggedValue jsKey(key);
25         if (jsKey.IsSymbol()) {
26             auto symbolString = JSSymbol::Cast(key.GetTaggedObject());
27             return symbolString->GetHashField();
28         }
29         if (jsKey.IsString()) {
30             auto keyString = reinterpret_cast<EcmaString *>(key.GetTaggedObject());
31             return EcmaStringAccessor(keyString).GetHashcode();
32         }
33     }
34     // key must be object
35     UNREACHABLE();
36 }
37 
IsMatch(const JSTaggedValue & key,const JSTaggedValue & other)38 bool NameDictionary::IsMatch(const JSTaggedValue &key, const JSTaggedValue &other)
39 {
40     return key == other;
41 }
42 
GetAllKeys(const JSThread * thread,int offset,TaggedArray * keyArray) const43 void NameDictionary::GetAllKeys(const JSThread *thread, int offset, TaggedArray *keyArray) const
44 {
45     int arrayIndex = 0;
46     int size = Size();
47     CVector<std::pair<JSTaggedValue, PropertyAttributes>> sortArr;
48     for (int hashIndex = 0; hashIndex < size; hashIndex++) {
49         JSTaggedValue key = GetKey(hashIndex);
50         if (!key.IsUndefined() && !key.IsHole()) {
51             PropertyAttributes attr = GetAttributes(hashIndex);
52             std::pair<JSTaggedValue, PropertyAttributes> pair(key, attr);
53             sortArr.push_back(pair);
54         }
55     }
56     std::sort(sortArr.begin(), sortArr.end(), CompKey);
57     for (const auto &entry : sortArr) {
58         keyArray->Set(thread, arrayIndex + offset, entry.first);
59         arrayIndex++;
60     }
61 }
62 
GetAllEnumKeys(const JSThread * thread,int offset,TaggedArray * keyArray,uint32_t * keys) const63 void NameDictionary::GetAllEnumKeys(const JSThread *thread, int offset, TaggedArray *keyArray, uint32_t *keys) const
64 {
65     uint32_t arrayIndex = 0;
66     int size = Size();
67     CVector<std::pair<JSTaggedValue, PropertyAttributes>> sortArr;
68     for (int hashIndex = 0; hashIndex < size; hashIndex++) {
69         JSTaggedValue key = GetKey(hashIndex);
70         if (key.IsString()) {
71             PropertyAttributes attr = GetAttributes(hashIndex);
72             if (attr.IsEnumerable()) {
73                 std::pair<JSTaggedValue, PropertyAttributes> pair(key, attr);
74                 sortArr.push_back(pair);
75             }
76         }
77     }
78     std::sort(sortArr.begin(), sortArr.end(), CompKey);
79     for (auto entry : sortArr) {
80         keyArray->Set(thread, arrayIndex + static_cast<uint32_t>(offset), entry.first);
81         arrayIndex++;
82     }
83     *keys += arrayIndex;
84 }
85 
Create(const JSThread * thread,int numberOfElements)86 JSHandle<NameDictionary> NameDictionary::Create(const JSThread *thread, int numberOfElements)
87 {
88     return OrderHashTableT::Create(thread, numberOfElements);
89 }
90 
GetAttributes(int entry) const91 PropertyAttributes NameDictionary::GetAttributes(int entry) const
92 {
93     int index = GetEntryIndex(entry) + ENTRY_DETAILS_INDEX;
94     return PropertyAttributes(Get(index).GetInt());
95 }
96 
SetAttributes(const JSThread * thread,int entry,const PropertyAttributes & metaData)97 void NameDictionary::SetAttributes(const JSThread *thread, int entry, const PropertyAttributes &metaData)
98 {
99     int index = GetEntryIndex(entry) + ENTRY_DETAILS_INDEX;
100     Set(thread, index, metaData.GetTaggedValue());
101 }
102 
SetEntry(const JSThread * thread,int entry,const JSTaggedValue & key,const JSTaggedValue & value,const PropertyAttributes & metaData)103 void NameDictionary::SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value,
104                               const PropertyAttributes &metaData)
105 {
106     SetKey(thread, entry, key);
107     SetValue(thread, entry, value);
108     SetAttributes(thread, entry, metaData);
109 }
110 
UpdateValueAndAttributes(const JSThread * thread,int entry,const JSTaggedValue & value,const PropertyAttributes & metaData)111 void NameDictionary::UpdateValueAndAttributes(const JSThread *thread, int entry, const JSTaggedValue &value,
112                                               const PropertyAttributes &metaData)
113 {
114     SetValue(thread, entry, value);
115     SetAttributes(thread, entry, metaData);
116 }
117 
UpdateValue(const JSThread * thread,int entry,const JSTaggedValue & value)118 void NameDictionary::UpdateValue(const JSThread *thread, int entry, const JSTaggedValue &value)
119 {
120     SetValue(thread, entry, value);
121 }
122 
ClearEntry(const JSThread * thread,int entry)123 void NameDictionary::ClearEntry(const JSThread *thread, int entry)
124 {
125     JSTaggedValue hole = JSTaggedValue::Hole();
126     PropertyAttributes metaData;
127     SetEntry(thread, entry, hole, hole, metaData);
128 }
129 
Hash(const JSTaggedValue & key)130 int NumberDictionary::Hash(const JSTaggedValue &key)
131 {
132     if (key.IsInt()) {
133         int keyValue = key.GetInt();
134         return GetHash32(reinterpret_cast<uint8_t *>(&keyValue), sizeof(keyValue) / sizeof(uint8_t));
135     }
136     // key must be object
137     UNREACHABLE();
138 }
139 
IsMatch(const JSTaggedValue & key,const JSTaggedValue & other)140 bool NumberDictionary::IsMatch(const JSTaggedValue &key, const JSTaggedValue &other)
141 {
142     if (key.IsHole() || key.IsUndefined()) {
143         return false;
144     }
145 
146     if (key.IsInt()) {
147         if (other.IsInt()) {
148             return key.GetInt() == other.GetInt();
149         }
150         return false;
151     }
152     // key must be integer
153     UNREACHABLE();
154 }
155 
GetAllKeys(const JSThread * thread,const JSHandle<NumberDictionary> & obj,int offset,const JSHandle<TaggedArray> & keyArray)156 void NumberDictionary::GetAllKeys(const JSThread *thread, const JSHandle<NumberDictionary> &obj, int offset,
157                                   const JSHandle<TaggedArray> &keyArray)
158 {
159     ASSERT_PRINT(offset + obj->EntriesCount() <= static_cast<int>(keyArray->GetLength()),
160                  "keyArray capacity is not enough for dictionary");
161     int arrayIndex = 0;
162     int size = obj->Size();
163     CVector<JSTaggedValue> sortArr;
164     for (int hashIndex = 0; hashIndex < size; hashIndex++) {
165         JSTaggedValue key = obj->GetKey(hashIndex);
166         if (!key.IsUndefined() && !key.IsHole()) {
167             sortArr.push_back(JSTaggedValue(static_cast<uint32_t>(key.GetInt())));
168         }
169     }
170     std::sort(sortArr.begin(), sortArr.end(), CompKey);
171     for (auto entry : sortArr) {
172         JSHandle<JSTaggedValue> keyHandle(thread, entry);
173         JSHandle<EcmaString> str = JSTaggedValue::ToString(const_cast<JSThread *>(thread), keyHandle);
174         ASSERT_NO_ABRUPT_COMPLETION(thread);
175         keyArray->Set(thread, arrayIndex + offset, str.GetTaggedValue());
176         arrayIndex++;
177     }
178 }
179 
GetAllEnumKeys(const JSThread * thread,const JSHandle<NumberDictionary> & obj,int offset,const JSHandle<TaggedArray> & keyArray,uint32_t * keys)180 void NumberDictionary::GetAllEnumKeys(const JSThread *thread, const JSHandle<NumberDictionary> &obj, int offset,
181                                       const JSHandle<TaggedArray> &keyArray, uint32_t *keys)
182 {
183     ASSERT_PRINT(offset + obj->EntriesCount() <= static_cast<int>(keyArray->GetLength()),
184                  "keyArray capacity is not enough for dictionary");
185     uint32_t arrayIndex = 0;
186     int size = obj->Size();
187     CVector<JSTaggedValue> sortArr;
188     for (int hashIndex = 0; hashIndex < size; hashIndex++) {
189         JSTaggedValue key = obj->GetKey(hashIndex);
190         if (!key.IsUndefined() && !key.IsHole()) {
191             PropertyAttributes attr = obj->GetAttributes(hashIndex);
192             if (attr.IsEnumerable()) {
193                 sortArr.push_back(JSTaggedValue(static_cast<uint32_t>(key.GetInt())));
194             }
195         }
196     }
197     std::sort(sortArr.begin(), sortArr.end(), CompKey);
198     for (auto entry : sortArr) {
199         JSHandle<JSTaggedValue> key_handle(thread, entry);
200         JSHandle<EcmaString> str = JSTaggedValue::ToString(const_cast<JSThread *>(thread), key_handle);
201         ASSERT_NO_ABRUPT_COMPLETION(thread);
202         keyArray->Set(thread, arrayIndex + static_cast<uint32_t>(offset), str.GetTaggedValue());
203         arrayIndex++;
204     }
205     *keys += arrayIndex;
206 }
207 
Create(const JSThread * thread,int numberOfElements)208 JSHandle<NumberDictionary> NumberDictionary::Create(const JSThread *thread, int numberOfElements)
209 {
210     return OrderHashTableT::Create(thread, numberOfElements);
211 }
212 
GetAttributes(int entry) const213 PropertyAttributes NumberDictionary::GetAttributes(int entry) const
214 {
215     int index = GetEntryIndex(entry) + ENTRY_DETAILS_INDEX;
216     return PropertyAttributes(Get(index).GetInt());
217 }
218 
SetAttributes(const JSThread * thread,int entry,const PropertyAttributes & metaData)219 void NumberDictionary::SetAttributes(const JSThread *thread, int entry, const PropertyAttributes &metaData)
220 {
221     int index = GetEntryIndex(entry) + ENTRY_DETAILS_INDEX;
222     Set(thread, index, metaData.GetTaggedValue());
223 }
224 
SetEntry(const JSThread * thread,int entry,const JSTaggedValue & key,const JSTaggedValue & value,const PropertyAttributes & metaData)225 void NumberDictionary::SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value,
226                                 const PropertyAttributes &metaData)
227 {
228     SetKey(thread, entry, key);
229     SetValue(thread, entry, value);
230     SetAttributes(thread, entry, metaData);
231 }
232 
UpdateValueAndAttributes(const JSThread * thread,int entry,const JSTaggedValue & value,const PropertyAttributes & metaData)233 void NumberDictionary::UpdateValueAndAttributes(const JSThread *thread, int entry, const JSTaggedValue &value,
234                                                 const PropertyAttributes &metaData)
235 {
236     SetValue(thread, entry, value);
237     SetAttributes(thread, entry, metaData);
238 }
239 
UpdateValue(const JSThread * thread,int entry,const JSTaggedValue & value)240 void NumberDictionary::UpdateValue(const JSThread *thread, int entry, const JSTaggedValue &value)
241 {
242     SetValue(thread, entry, value);
243 }
244 
ClearEntry(const JSThread * thread,int entry)245 void NumberDictionary::ClearEntry(const JSThread *thread, int entry)
246 {
247     JSTaggedValue hole = JSTaggedValue::Hole();
248     PropertyAttributes metaData;
249     SetEntry(thread, entry, hole, hole, metaData);
250 }
251 }  // namespace panda::ecmascript
252