• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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/js_api/js_api_lightweightmap.h"
17 
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/js_array.h"
20 #include "ecmascript/js_function.h"
21 #include "ecmascript/js_handle.h"
22 #include "ecmascript/js_object-inl.h"
23 #include "ecmascript/js_tagged_number.h"
24 #include "ecmascript/js_tagged_value.h"
25 #include "ecmascript/object_factory.h"
26 
27 namespace panda::ecmascript {
28 using ContainerError = containers::ContainerError;
29 using ErrorFlag = containers::ErrorFlag;
IncreaseCapacityTo(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,int32_t index)30 JSTaggedValue JSAPILightWeightMap::IncreaseCapacityTo(JSThread *thread,
31                                                       const JSHandle<JSAPILightWeightMap> &lightWeightMap,
32                                                       int32_t index)
33 {
34     int32_t num = lightWeightMap->GetSize();
35     if (index < DEFAULT_CAPACITY_LENGTH || num >= index) {
36         return JSTaggedValue::False();
37     }
38     JSHandle<TaggedArray> hashArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::HASH);
39     JSHandle<TaggedArray> keyArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::KEY);
40     JSHandle<TaggedArray> valueArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::VALUE);
41     JSHandle<TaggedArray> newHashArray = GrowCapacity(thread, hashArray, index);
42     JSHandle<TaggedArray> newKeyArray = GrowCapacity(thread, keyArray, index);
43     JSHandle<TaggedArray> newValueArray = GrowCapacity(thread, valueArray, index);
44     lightWeightMap->SetHashes(thread, newHashArray);
45     lightWeightMap->SetKeys(thread, newKeyArray);
46     lightWeightMap->SetValues(thread, newValueArray);
47     return JSTaggedValue::True();
48 }
49 
InsertValue(const JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,int32_t index,const JSHandle<JSTaggedValue> & value,AccossorsKind kind)50 void JSAPILightWeightMap::InsertValue(const JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
51                                       int32_t index, const JSHandle<JSTaggedValue> &value, AccossorsKind kind)
52 {
53     JSHandle<TaggedArray> array = GetArrayByKind(thread, lightWeightMap, kind);
54     int32_t len = lightWeightMap->GetSize();
55     JSHandle<TaggedArray> newArray = GrowCapacity(thread, array, len + 1);
56     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
57     newArray = factory->InsertElementByIndex(newArray, value, index, len);
58     SetArrayByKind(thread, lightWeightMap, newArray, kind);
59 }
60 
ReplaceValue(const JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,int32_t index,const JSHandle<JSTaggedValue> & value,AccossorsKind kind)61 void JSAPILightWeightMap::ReplaceValue(const JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
62                                        int32_t index, const JSHandle<JSTaggedValue> &value, AccossorsKind kind)
63 {
64     JSHandle<TaggedArray> array = GetArrayByKind(thread, lightWeightMap, kind);
65     ASSERT(0 <= index || index < lightWeightMap->GetSize());
66     array->Set(thread, index, value.GetTaggedValue());
67 }
68 
RemoveValue(const JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,uint32_t index,AccossorsKind kind)69 void JSAPILightWeightMap::RemoveValue(const JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
70                                       uint32_t index, AccossorsKind kind)
71 {
72     JSHandle<TaggedArray> array = GetArrayByKind(thread, lightWeightMap, kind);
73     uint32_t len = lightWeightMap->GetLength();
74     ASSERT(index < len);
75     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
76     factory->RemoveElementByIndex(array, index, len);
77 }
78 
Set(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)79 void JSAPILightWeightMap::Set(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
80                               const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value)
81 {
82     KeyState keyState = GetStateOfKey(thread, lightWeightMap, key);
83     int32_t index = keyState.index;
84     if (keyState.existed) {
85         ReplaceValue(thread, lightWeightMap, index, value, AccossorsKind::VALUE);
86     } else {
87         JSHandle<JSTaggedValue> hashHandle(thread, JSTaggedValue(keyState.hash));
88         InsertValue(thread, lightWeightMap, index, hashHandle, AccossorsKind::HASH);
89         InsertValue(thread, lightWeightMap, index, key, AccossorsKind::KEY);
90         InsertValue(thread, lightWeightMap, index, value, AccossorsKind::VALUE);
91         lightWeightMap->SetLength(lightWeightMap->GetLength() + 1);
92     }
93 }
94 
Get(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSTaggedValue> & key)95 JSTaggedValue JSAPILightWeightMap::Get(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
96                                        const JSHandle<JSTaggedValue> &key)
97 {
98     int32_t index = GetIndexOfKey(thread, lightWeightMap, key);
99     if (index < 0) {
100         return JSTaggedValue::Undefined();
101     }
102     JSHandle<TaggedArray> valueArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::VALUE);
103     return valueArray->Get(index);
104 }
105 
HasAll(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSAPILightWeightMap> & newLightWeightMap)106 JSTaggedValue JSAPILightWeightMap::HasAll(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
107                                           const JSHandle<JSAPILightWeightMap> &newLightWeightMap)
108 {
109     int32_t length = newLightWeightMap->GetSize();
110     int32_t len = lightWeightMap->GetSize();
111     if (length > len) {
112         return JSTaggedValue::False();
113     }
114     JSHandle<TaggedArray> oldHashArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::HASH);
115     JSHandle<TaggedArray> oldKeyArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::KEY);
116     JSHandle<TaggedArray> oldValueArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::VALUE);
117     JSHandle<TaggedArray> newKeyArray = GetArrayByKind(thread, newLightWeightMap, AccossorsKind::KEY);
118     JSHandle<TaggedArray> newValueArray = GetArrayByKind(thread, newLightWeightMap, AccossorsKind::VALUE);
119     JSTaggedValue dealKey = JSTaggedValue::Undefined();
120     int32_t index = -1;
121     int32_t hash = 0;
122 
123     for (int32_t num = 0; num < length; num++) {
124         dealKey = newKeyArray->Get(num);
125         hash = Hash(dealKey);
126         index = BinarySearchHashes(oldHashArray, hash, len);
127         if (index < 0 || index >= len) {
128             return JSTaggedValue::False();
129         }
130         HashParams params { oldHashArray, oldKeyArray, &dealKey };
131         index = AvoidHashCollision(params, index, len, hash);
132         if (!JSTaggedValue::SameValue(oldKeyArray->Get(index), dealKey) ||
133             !JSTaggedValue::SameValue(oldValueArray->Get(index), newValueArray->Get(num))) {
134             // avoid Hash collision
135             return JSTaggedValue::False();
136         }
137     }
138     return JSTaggedValue::True();
139 }
140 
HasKey(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSTaggedValue> & key)141 JSTaggedValue JSAPILightWeightMap::HasKey(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
142                                           const JSHandle<JSTaggedValue> &key)
143 {
144     KeyState keyState = GetStateOfKey(thread, lightWeightMap, key);
145     return keyState.existed ? JSTaggedValue::True() : JSTaggedValue::False();
146 }
147 
HasValue(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSTaggedValue> & value)148 JSTaggedValue JSAPILightWeightMap::HasValue(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
149                                             const JSHandle<JSTaggedValue> &value)
150 {
151     JSHandle<TaggedArray> valueArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::VALUE);
152     int32_t length = lightWeightMap->GetSize();
153     for (int32_t num = 0; num < length; num++) {
154         if (JSTaggedValue::SameValue(valueArray->Get(num), value.GetTaggedValue())) {
155             return JSTaggedValue::True();
156         }
157     }
158     return JSTaggedValue::False();
159 }
160 
GetIndexOfKey(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSTaggedValue> & key)161 int32_t JSAPILightWeightMap::GetIndexOfKey(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
162                                            const JSHandle<JSTaggedValue> &key)
163 {
164     KeyState keyState = GetStateOfKey(thread, lightWeightMap, key);
165     return keyState.existed ? keyState.index : -1;
166 }
167 
GetStateOfKey(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSTaggedValue> & key)168 KeyState JSAPILightWeightMap::GetStateOfKey(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
169                                             const JSHandle<JSTaggedValue> &key)
170 {
171     int32_t hash = Hash(key.GetTaggedValue());
172     int32_t length = lightWeightMap->GetSize();
173     JSHandle<TaggedArray> hashArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::HASH);
174     int32_t index = BinarySearchHashes(hashArray, hash, length);
175     if (index >= 0) {
176         // avoid Hash Collision
177         JSHandle<TaggedArray> keyArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::KEY);
178         int32_t right = index;
179         while ((right < length) && (hashArray->Get(right).GetInt() == hash)) {
180             if (JSTaggedValue::SameValue(keyArray->Get(right), key.GetTaggedValue())) {
181                 return KeyState {true, hash, right};
182             }
183             right++;
184         }
185         int32_t left = index - 1;
186         while ((left >= 0) && ((hashArray->Get(left).GetInt() == hash))) {
187             if (JSTaggedValue::SameValue(keyArray->Get(left), key.GetTaggedValue())) {
188                 return KeyState {true, hash, left};
189             }
190             left--;
191         }
192         return KeyState {false, hash, right}; // first index whose element is bigger than hash
193     }
194     return KeyState {false, hash, index ^ HASH_REBELLION}; // first index whose element is bigger than hash
195 }
196 
GetIndexOfValue(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSTaggedValue> & value)197 int32_t JSAPILightWeightMap::GetIndexOfValue(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
198                                              const JSHandle<JSTaggedValue> &value)
199 {
200     JSHandle<TaggedArray> valueArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::VALUE);
201     int32_t length = lightWeightMap->GetSize();
202     JSTaggedValue compValue = value.GetTaggedValue();
203     for (int32_t i = 0; i < length; i++) {
204         if (valueArray->Get(i) == compValue) {
205             return i;
206         }
207     }
208     return -1; // not find, default return -1
209 }
210 
GetKeyAt(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,int32_t index)211 JSTaggedValue JSAPILightWeightMap::GetKeyAt(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
212                                             int32_t index)
213 {
214     int32_t length = lightWeightMap->GetSize();
215     if (index < 0 || length <= index) {
216         std::ostringstream oss;
217         oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1)
218             << ". Received value is: " << index;
219         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
220         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
221     }
222     JSHandle<TaggedArray> keyArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::KEY);
223     return keyArray->Get(index);
224 }
225 
GetValueAt(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,int32_t index)226 JSTaggedValue JSAPILightWeightMap::GetValueAt(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
227                                               int32_t index)
228 {
229     int32_t length = lightWeightMap->GetSize();
230     if (index < 0 || length <= index) {
231         std::ostringstream oss;
232         oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1)
233             << ". Received value is: " << index;
234         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
235         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
236     }
237     JSHandle<TaggedArray> valueArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::VALUE);
238     return valueArray->Get(index);
239 }
240 
SetAll(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSAPILightWeightMap> & needLightWeightMap)241 void JSAPILightWeightMap::SetAll(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
242                                  const JSHandle<JSAPILightWeightMap> &needLightWeightMap)
243 {
244     JSHandle<TaggedArray> needKeyArray = GetArrayByKind(thread, needLightWeightMap, AccossorsKind::KEY);
245     JSHandle<TaggedArray> needValueArray = GetArrayByKind(thread, needLightWeightMap, AccossorsKind::VALUE);
246     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
247     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
248     int32_t length = needLightWeightMap->GetSize();
249     for (int32_t num = 0; num < length; num++) {
250         key.Update(needKeyArray->Get(num));
251         value.Update(needValueArray->Get(num));
252         JSAPILightWeightMap::Set(thread, lightWeightMap, key, value);
253     }
254 }
255 
Remove(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<JSTaggedValue> & key)256 JSTaggedValue JSAPILightWeightMap::Remove(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
257                                           const JSHandle<JSTaggedValue> &key)
258 {
259     KeyState keyState = GetStateOfKey(thread, lightWeightMap, key);
260     if (!keyState.existed) {
261         return JSTaggedValue::Undefined();
262     }
263     int32_t index = keyState.index;
264     JSHandle<TaggedArray> valueArray = GetArrayByKind(thread, lightWeightMap, AccossorsKind::VALUE);
265     JSTaggedValue value = valueArray->Get(index);
266     RemoveValue(thread, lightWeightMap, index, AccossorsKind::HASH);
267     RemoveValue(thread, lightWeightMap, index, AccossorsKind::VALUE);
268     RemoveValue(thread, lightWeightMap, index, AccossorsKind::KEY);
269     lightWeightMap->SetLength(lightWeightMap->GetLength() - 1);
270     return value;
271 }
272 
RemoveAt(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,int32_t index)273 JSTaggedValue JSAPILightWeightMap::RemoveAt(JSThread *thread,
274                                             const JSHandle<JSAPILightWeightMap> &lightWeightMap, int32_t index)
275 {
276     int32_t length = lightWeightMap->GetSize();
277     if (index < 0 || length <= index) {
278         return JSTaggedValue::False();
279     }
280     RemoveValue(thread, lightWeightMap, index, AccossorsKind::HASH);
281     RemoveValue(thread, lightWeightMap, index, AccossorsKind::VALUE);
282     RemoveValue(thread, lightWeightMap, index, AccossorsKind::KEY);
283     lightWeightMap->SetLength(length - 1);
284     return JSTaggedValue::True();
285 }
286 
IsEmpty()287 JSTaggedValue JSAPILightWeightMap::IsEmpty()
288 {
289     if (GetLength() == 0) {
290         return JSTaggedValue::True();
291     } else {
292         return JSTaggedValue::False();
293     }
294 }
295 
Clear(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap)296 void JSAPILightWeightMap::Clear(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap)
297 {
298     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
299     JSHandle<JSTaggedValue> hashArray = JSHandle<JSTaggedValue>(factory->NewTaggedArray(DEFAULT_CAPACITY_LENGTH));
300     JSHandle<JSTaggedValue> keyArray = JSHandle<JSTaggedValue>(factory->NewTaggedArray(DEFAULT_CAPACITY_LENGTH));
301     JSHandle<JSTaggedValue> valueArray = JSHandle<JSTaggedValue>(factory->NewTaggedArray(DEFAULT_CAPACITY_LENGTH));
302     lightWeightMap->SetHashes(thread, hashArray);
303     lightWeightMap->SetKeys(thread, keyArray);
304     lightWeightMap->SetValues(thread, valueArray);
305     lightWeightMap->SetLength(0);
306 }
307 
SetValueAt(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,int32_t index,const JSHandle<JSTaggedValue> & value)308 JSTaggedValue JSAPILightWeightMap::SetValueAt(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap,
309                                               int32_t index, const JSHandle<JSTaggedValue> &value)
310 {
311     int32_t length = lightWeightMap->GetSize();
312     if (index < 0 || length <= index) {
313         std::ostringstream oss;
314         oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1)
315             << ". Received value is: " << index;
316         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
317         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
318     }
319     ReplaceValue(thread, lightWeightMap, index, value, AccossorsKind::VALUE);
320     return JSTaggedValue::True();
321 }
322 
AvoidHashCollision(HashParams & params,int32_t index,int32_t size,int32_t hash)323 int32_t JSAPILightWeightMap::AvoidHashCollision(HashParams &params, int32_t index, int32_t size, int32_t hash)
324 {
325     int32_t right = index;
326     while ((right < size) && ((params.hashArray)->Get(right).GetInt() == hash)) {
327         if (JSTaggedValue::SameValue((params.keyArray)->Get(right), *(params.key))) {
328             return right;
329         }
330         right++;
331     }
332     int32_t left = index - 1;
333     while ((left >= 0) && ((params.hashArray)->Get(left).GetInt() == hash)) {
334         if (JSTaggedValue::SameValue((params.keyArray)->Get(left), *(params.key))) {
335             return left;
336         }
337         left--;
338     }
339 
340     int32_t res = (-right) ^ HASH_REBELLION;
341     return res;
342 }
343 
GetIteratorObj(JSThread * thread,const JSHandle<JSAPILightWeightMap> & obj,IterationKind type)344 JSTaggedValue JSAPILightWeightMap::GetIteratorObj(JSThread *thread, const JSHandle<JSAPILightWeightMap> &obj,
345                                                   IterationKind type)
346 {
347     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
348     JSHandle<JSAPILightWeightMapIterator> iter(factory->NewJSAPILightWeightMapIterator(obj, type));
349 
350     return iter.GetTaggedValue();
351 }
352 
ToString(JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap)353 JSTaggedValue JSAPILightWeightMap::ToString(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap)
354 {
355     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
356     std::u16string sepStr = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(",");
357     std::u16string colonStr = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(":");
358     uint32_t length = lightWeightMap->GetLength();
359     std::u16string concatStr;
360     JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
361     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
362 
363     for (uint32_t k = 0; k < length; k++) {
364         std::u16string valueStr;
365         valueHandle.Update(lightWeightMap->GetValueAt(thread, lightWeightMap, k));
366         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
367         if (!valueHandle->IsUndefined() && !valueHandle->IsNull()) {
368             JSHandle<EcmaString> valueStringHandle = JSTaggedValue::ToString(thread, valueHandle);
369             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
370             valueStr = EcmaStringAccessor(valueStringHandle).ToU16String();
371         }
372 
373         std::u16string nextStr;
374         keyHandle.Update(lightWeightMap->GetKeyAt(thread, lightWeightMap, k));
375         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
376         if (!keyHandle->IsUndefined() && !keyHandle->IsNull()) {
377             JSHandle<EcmaString> keyStringHandle = JSTaggedValue::ToString(thread, keyHandle);
378             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
379             nextStr = EcmaStringAccessor(keyStringHandle).ToU16String();
380         }
381 
382         nextStr.append(colonStr);
383         nextStr.append(valueStr);
384 
385         if (k > 0) {
386             concatStr.append(sepStr);
387             concatStr.append(nextStr);
388             continue;
389         }
390         concatStr.append(nextStr);
391     }
392 
393     char16_t *char16tData = concatStr.data();
394     auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData);
395     uint32_t u16strSize = concatStr.size();
396     return factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue();
397 }
398 
GrowCapacity(const JSThread * thread,JSHandle<TaggedArray> & oldArray,uint32_t needCapacity)399 JSHandle<TaggedArray> JSAPILightWeightMap::GrowCapacity(const JSThread *thread, JSHandle<TaggedArray> &oldArray,
400                                                         uint32_t needCapacity)
401 {
402     uint32_t oldLength = oldArray->GetLength();
403     if (needCapacity <= oldLength) {
404         return oldArray;
405     }
406     uint32_t newCapacity = ComputeCapacity(needCapacity);
407     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
408     JSHandle<TaggedArray> newArray = factory->CopyArray(oldArray, oldLength, newCapacity);
409     return newArray;
410 }
411 
SetArrayByKind(const JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,const JSHandle<TaggedArray> & array,AccossorsKind kind)412 void JSAPILightWeightMap::SetArrayByKind(const JSThread *thread,
413                                          const JSHandle<JSAPILightWeightMap> &lightWeightMap,
414                                          const JSHandle<TaggedArray> &array,
415                                          AccossorsKind kind)
416 {
417     switch (kind) {
418         case AccossorsKind::HASH:
419             lightWeightMap->SetHashes(thread, array);
420             break;
421         case AccossorsKind::KEY:
422             lightWeightMap->SetKeys(thread, array);
423             break;
424         case AccossorsKind::VALUE:
425             lightWeightMap->SetValues(thread, array);
426             break;
427         default:
428             UNREACHABLE();
429     }
430 }
431 
GetArrayByKind(const JSThread * thread,const JSHandle<JSAPILightWeightMap> & lightWeightMap,AccossorsKind kind)432 JSHandle<TaggedArray> JSAPILightWeightMap::GetArrayByKind(const JSThread *thread,
433                                                           const JSHandle<JSAPILightWeightMap> &lightWeightMap,
434                                                           AccossorsKind kind)
435 {
436     JSHandle<TaggedArray> array;
437     switch (kind) {
438         case AccossorsKind::HASH:
439             array = JSHandle<TaggedArray>(thread, lightWeightMap->GetHashes());
440             break;
441         case AccossorsKind::KEY:
442             array = JSHandle<TaggedArray>(thread, lightWeightMap->GetKeys());
443             break;
444         case AccossorsKind::VALUE:
445             array = JSHandle<TaggedArray>(thread, lightWeightMap->GetValues());
446             break;
447         default:
448             UNREACHABLE();
449     }
450     return array;
451 }
452 
Hash(JSTaggedValue key)453 int32_t JSAPILightWeightMap::Hash(JSTaggedValue key)
454 {
455     if (key.IsDouble() && key.GetDouble() == 0.0) {
456         key = JSTaggedValue(0);
457     }
458     if (key.IsSymbol()) {
459         auto symbolString = JSSymbol::Cast(key.GetTaggedObject());
460         return symbolString->GetHashField();
461     }
462     if (key.IsString()) {
463         auto keyString = EcmaString::Cast(key.GetTaggedObject());
464         return EcmaStringAccessor(keyString).GetHashcode();
465     }
466     if (key.IsECMAObject()) {
467         uint32_t hash = ECMAObject::Cast(key.GetTaggedObject())->GetHash();
468         if (hash == 0) {
469             uint64_t keyValue = key.GetRawData();
470             hash = GetHash32(reinterpret_cast<uint8_t *>(&keyValue), sizeof(keyValue) / sizeof(uint8_t));
471             ECMAObject::Cast(key.GetTaggedObject())->SetHash(hash);
472         }
473         return hash;
474     }
475     if (key.IsInt()) {
476         int32_t hash = key.GetInt();
477         return hash;
478     }
479     uint64_t keyValue = key.GetRawData();
480     return GetHash32(reinterpret_cast<uint8_t *>(&keyValue), sizeof(keyValue) / sizeof(uint8_t));
481 }
482 
BinarySearchHashes(JSHandle<TaggedArray> & array,int32_t hash,int32_t size)483 int32_t JSAPILightWeightMap::BinarySearchHashes(JSHandle<TaggedArray> &array, int32_t hash, int32_t size)
484 {
485     int32_t low = 0;
486     int32_t high = size - 1;
487     while (low <= high) {
488         uint32_t mid = static_cast<uint32_t>(low + high) >> 1U;
489         int32_t midHash = array->Get(mid).GetInt();
490         if (midHash < hash) {
491             low = static_cast<int32_t>(mid) + 1;
492         } else {
493             if (midHash == hash) {
494                 return mid;
495             }
496             high = static_cast<int32_t>(mid) - 1;
497         }
498     }
499     return -(low + 1);
500 }
501 }  // namespace panda::ecmascript
502