• 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_lightweightset.h"
17 
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/js_api/js_api_lightweightset_iterator.h"
21 #include "ecmascript/js_array.h"
22 #include "ecmascript/js_function.h"
23 #include "ecmascript/js_tagged_value.h"
24 #include "ecmascript/object_factory.h"
25 
26 namespace panda::ecmascript {
27 using ContainerError = containers::ContainerError;
28 using ErrorFlag = containers::ErrorFlag;
Add(JSThread * thread,const JSHandle<JSAPILightWeightSet> & obj,const JSHandle<JSTaggedValue> & value)29 bool JSAPILightWeightSet::Add(JSThread *thread, const JSHandle<JSAPILightWeightSet> &obj,
30                               const JSHandle<JSTaggedValue> &value)
31 {
32     CheckAndCopyValues(thread, obj);
33     uint32_t hashCode = obj->Hash(thread, value.GetTaggedValue());
34     JSHandle<TaggedArray> hashArray(thread, obj->GetHashes());
35     JSHandle<TaggedArray> valueArray(thread, obj->GetValues());
36     int32_t size = static_cast<int32_t>(obj->GetLength());
37     int32_t index = obj->GetHashIndex(thread, value, size);
38     if (index >= 0) {
39         return false;
40     }
41     index ^= JSAPILightWeightSet::HASH_REBELLION;
42     if (index < size) {
43         obj->AdjustArray(thread, hashArray, index, size, true);
44         obj->AdjustArray(thread, valueArray, index, size, true);
45     }
46     uint32_t capacity = hashArray->GetLength();
47     if (size + 1 >= static_cast<int32_t>(capacity)) {
48         // need expanding
49         uint32_t newCapacity = capacity << 1U;
50         hashArray = thread->GetEcmaVM()->GetFactory()->CopyArray(hashArray, capacity, newCapacity);
51         valueArray = thread->GetEcmaVM()->GetFactory()->CopyArray(valueArray, capacity, newCapacity);
52         obj->SetHashes(thread, hashArray);
53         obj->SetValues(thread, valueArray);
54     }
55     hashArray->Set(thread, index, JSTaggedValue(hashCode));
56     valueArray->Set(thread, index, value.GetTaggedValue());
57     size++;
58     obj->SetLength(size);
59     return true;
60 }
61 
Get(const uint32_t index)62 JSTaggedValue JSAPILightWeightSet::Get(const uint32_t index)
63 {
64     TaggedArray *valueArray = TaggedArray::Cast(GetValues().GetTaggedObject());
65     return valueArray->Get(index);
66 }
67 
CreateSlot(const JSThread * thread,const uint32_t capacity)68 JSHandle<TaggedArray> JSAPILightWeightSet::CreateSlot(const JSThread *thread, const uint32_t capacity)
69 {
70     ASSERT_PRINT(capacity > 0, "size must be a non-negative integer");
71     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
72     JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(capacity);
73     for (uint32_t i = 0; i < capacity; i++) {
74         taggedArray->Set(thread, i, JSTaggedValue::Hole());
75     }
76     return taggedArray;
77 }
78 
GetHashIndex(const JSThread * thread,const JSHandle<JSTaggedValue> & value,int32_t size)79 int32_t JSAPILightWeightSet::GetHashIndex(const JSThread *thread, const JSHandle<JSTaggedValue> &value, int32_t size)
80 {
81     uint32_t hashCode = Hash(thread, value.GetTaggedValue());
82     int32_t index = BinarySearchHashes(hashCode, size);
83     if (index < 0) {
84         return index;
85     }
86     TaggedArray *valueArray = TaggedArray::Cast(GetValues().GetTaggedObject());
87     if (index < size && (JSTaggedValue::SameValue(valueArray->Get(index), value.GetTaggedValue()))) {
88         return index;
89     }
90     TaggedArray *hashArray = TaggedArray::Cast(GetHashes().GetTaggedObject());
91     int32_t right = index;
92     while (right < size && (hashArray->Get(right).GetNumber() == hashCode)) {
93         if (JSTaggedValue::SameValue(valueArray->Get(right), value.GetTaggedValue())) {
94             return right;
95         }
96         right++;
97     }
98     int32_t left = index - 1;
99     while (left >= 0 && ((hashArray->Get(left).GetNumber() == hashCode))) {
100         if (JSTaggedValue::SameValue(valueArray->Get(left), value.GetTaggedValue())) {
101             return left;
102         }
103         left--;
104     }
105     return -right;
106 }
107 
BinarySearchHashes(uint32_t hash,int32_t size)108 int32_t JSAPILightWeightSet::BinarySearchHashes(uint32_t hash, int32_t size)
109 {
110     int32_t low = 0;
111     int32_t high = size - 1;
112     TaggedArray *hashArray = TaggedArray::Cast(GetHashes().GetTaggedObject());
113     while (low <= high) {
114         uint32_t mid = static_cast<uint32_t>(low + high) >> 1U;
115         uint32_t midVal = (uint32_t)(hashArray->Get(mid).GetNumber());
116         if (midVal < hash) {
117             low = mid + 1;
118         } else {
119             if (midVal <= hash) {
120                 return mid;
121             }
122             high = mid - 1;
123         }
124     }
125     return -(low + 1);
126 }
127 
AddAll(JSThread * thread,const JSHandle<JSAPILightWeightSet> & obj,const JSHandle<JSTaggedValue> & value)128 bool JSAPILightWeightSet::AddAll(JSThread *thread, const JSHandle<JSAPILightWeightSet> &obj,
129                                  const JSHandle<JSTaggedValue> &value)
130 {
131     bool changed = false;
132     JSHandle<JSAPILightWeightSet> srcLightWeightSet = JSHandle<JSAPILightWeightSet>::Cast(value);
133     uint32_t srcSize = srcLightWeightSet->GetSize();
134     uint32_t size = obj->GetSize();
135     obj->EnsureCapacity(thread, obj, size + srcSize);
136     JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
137     for (uint32_t i = 0; i < srcSize; i++) {
138         element.Update(srcLightWeightSet->GetValueAt(i));
139         changed |= JSAPILightWeightSet::Add(thread, obj, element);
140     }
141     return changed;
142 }
143 
EnsureCapacity(const JSThread * thread,const JSHandle<JSAPILightWeightSet> & obj,uint32_t minimumCapacity)144 void JSAPILightWeightSet::EnsureCapacity(const JSThread *thread, const JSHandle<JSAPILightWeightSet> &obj,
145                                          uint32_t minimumCapacity)
146 {
147     TaggedArray *hashes = TaggedArray::Cast(obj->GetValues().GetTaggedObject());
148     uint32_t capacity = hashes->GetLength();
149     uint32_t newCapacity = capacity;
150     if (capacity > minimumCapacity) {
151         return;
152     }
153     // adjust
154     while (newCapacity <= minimumCapacity) {
155         newCapacity = newCapacity << 1U;
156     }
157     obj->SizeCopy(thread, obj, capacity, newCapacity);
158 }
159 
SizeCopy(const JSThread * thread,const JSHandle<JSAPILightWeightSet> & obj,uint32_t capacity,uint32_t newCapacity)160 void JSAPILightWeightSet::SizeCopy(const JSThread *thread, const JSHandle<JSAPILightWeightSet> &obj,
161                                    uint32_t capacity, uint32_t newCapacity)
162 {
163     JSHandle<TaggedArray> hashArray(thread, obj->GetHashes());
164     JSHandle<TaggedArray> valueArray(thread, obj->GetValues());
165     hashArray = thread->GetEcmaVM()->GetFactory()->CopyArray(hashArray, capacity, newCapacity);
166     valueArray = thread->GetEcmaVM()->GetFactory()->CopyArray(valueArray, capacity, newCapacity);
167 
168     obj->SetValues(thread, hashArray);
169     obj->SetHashes(thread, valueArray);
170 }
171 
IsEmpty()172 bool JSAPILightWeightSet::IsEmpty()
173 {
174     return GetLength() == 0;
175 }
176 
GetValueAt(int32_t index)177 JSTaggedValue JSAPILightWeightSet::GetValueAt(int32_t index)
178 {
179     int32_t size = static_cast<int32_t>(GetLength());
180     if (index < 0 || index >= size) {
181         return JSTaggedValue::Undefined();
182     }
183     TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
184     return values->Get(index);
185 }
186 
GetHashAt(int32_t index)187 JSTaggedValue JSAPILightWeightSet::GetHashAt(int32_t index)
188 {
189     int32_t size = static_cast<int32_t>(GetLength());
190     if (index < 0 || index >= size) {
191         return JSTaggedValue::Undefined();
192     }
193     TaggedArray *values = TaggedArray::Cast(GetHashes().GetTaggedObject());
194     return values->Get(index);
195 }
196 
HasAll(const JSHandle<JSTaggedValue> & value)197 bool JSAPILightWeightSet::HasAll(const JSHandle<JSTaggedValue> &value)
198 {
199     bool result = false;
200     uint32_t relocate = 0;
201     JSAPILightWeightSet *lightweightSet = JSAPILightWeightSet::Cast(value.GetTaggedValue().GetTaggedObject());
202     uint32_t size = GetLength();
203     uint32_t destSize = lightweightSet->GetLength();
204     TaggedArray *hashes = TaggedArray::Cast(GetHashes().GetTaggedObject());
205     TaggedArray *destHashes = TaggedArray::Cast(lightweightSet->GetHashes().GetTaggedObject());
206     if (destSize > size) {
207         return result;
208     }
209     for (uint32_t i = 0; i < destSize; i++) {
210         uint32_t destHashCode = destHashes->Get(i).GetNumber();
211         result = false;
212         for (uint32_t j = relocate; j < size; j++) {
213             uint32_t hashCode = hashes->Get(j).GetNumber();
214             if (destHashCode == hashCode) {
215                 result = true;
216                 relocate = j + 1;
217                 break;
218             }
219         }
220         if (!result) {
221             break;
222         }
223     }
224     return result;
225 }
226 
Has(const JSThread * thread,const JSHandle<JSTaggedValue> & value)227 bool JSAPILightWeightSet::Has(const JSThread *thread, const JSHandle<JSTaggedValue> &value)
228 {
229     uint32_t size = GetLength();
230     int32_t index = GetHashIndex(thread, value, size);
231     if (index < 0) {
232         return false;
233     }
234     return true;
235 }
236 
HasHash(const JSHandle<JSTaggedValue> & hashCode)237 bool JSAPILightWeightSet::HasHash(const JSHandle<JSTaggedValue> &hashCode)
238 {
239     uint32_t size = GetLength();
240     int32_t index = BinarySearchHashes(hashCode.GetTaggedValue().GetNumber(), size);
241     if (index < 0) {
242         return false;
243     }
244     return true;
245 }
246 
Equal(JSThread * thread,const JSHandle<JSAPILightWeightSet> & obj,const JSHandle<JSTaggedValue> & value)247 bool JSAPILightWeightSet::Equal(JSThread *thread, const JSHandle<JSAPILightWeightSet> &obj,
248                                 const JSHandle<JSTaggedValue> &value)
249 {
250     bool result = false;
251     JSHandle<TaggedArray> destHashes(thread, obj->GetValues());
252     uint32_t destSize = obj->GetLength();
253     uint32_t srcSize = 0;
254     JSMutableHandle<TaggedArray> srcHashes(thread, obj->GetHashes());
255     if (value.GetTaggedValue().IsJSAPILightWeightSet()) {
256         JSAPILightWeightSet *srcLightWeightSet = JSAPILightWeightSet::Cast(value.GetTaggedValue().GetTaggedObject());
257         srcSize = srcLightWeightSet->GetLength();
258         if (srcSize == 0 || destSize == 0) {
259             return false;
260         }
261         srcHashes.Update(srcLightWeightSet->GetHashes());
262     }
263     if (value.GetTaggedValue().IsJSArray()) {
264         srcHashes.Update(JSArray::ToTaggedArray(thread, value));
265         srcSize = srcHashes->GetLength();
266         if (srcSize == 0 || destSize == 0) {
267             return false;
268         }
269     }
270     if (srcSize != destSize) {
271         return false;
272     }
273     for (uint32_t i = 0; i < destSize; i++) {
274         JSTaggedValue compareValue = destHashes->Get(i);
275         JSTaggedValue values = srcHashes->Get(i);
276         if (compareValue.IsNumber() && values.IsNumber()) {
277             result = JSTaggedValue::SameValueNumberic(compareValue, values);
278         }
279         if (compareValue.IsString() && values.IsString()) {
280             result =
281                 JSTaggedValue::StringCompare(EcmaString::Cast(compareValue.GetTaggedObject()),
282                                              EcmaString::Cast(values.GetTaggedObject()));
283         }
284         if (!result) {
285             return result;
286         }
287     }
288     return result;
289 }
290 
IncreaseCapacityTo(JSThread * thread,const JSHandle<JSAPILightWeightSet> & obj,int32_t minCapacity)291 void JSAPILightWeightSet::IncreaseCapacityTo(JSThread *thread, const JSHandle<JSAPILightWeightSet> &obj,
292                                              int32_t minCapacity)
293 {
294     uint32_t capacity = TaggedArray::Cast(obj->GetValues().GetTaggedObject())->GetLength();
295     int32_t intCapacity = static_cast<int32_t>(capacity);
296     if (minCapacity <= 0 || intCapacity >= minCapacity) {
297         std::ostringstream oss;
298         oss << "The value of \"minimumCapacity\" is out of range. It must be > " << intCapacity
299             << ". Received value is: " << minCapacity;
300         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
301         THROW_NEW_ERROR_AND_RETURN(thread, error);
302     }
303     JSHandle<TaggedArray> hashArray(thread, obj->GetHashes());
304     JSHandle<TaggedArray> newElements =
305         thread->GetEcmaVM()->GetFactory()->NewAndCopyTaggedArray(hashArray,
306                                                                  static_cast<uint32_t>(minCapacity), capacity);
307     obj->SetHashes(thread, newElements);
308 }
309 
GetIteratorObj(JSThread * thread,const JSHandle<JSAPILightWeightSet> & obj,IterationKind kind)310 JSHandle<JSTaggedValue> JSAPILightWeightSet::GetIteratorObj(JSThread *thread, const JSHandle<JSAPILightWeightSet> &obj,
311                                                             IterationKind kind)
312 {
313     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
314     JSHandle<JSTaggedValue> iter =
315         JSHandle<JSTaggedValue>::Cast(factory->NewJSAPILightWeightSetIterator(obj, kind));
316     return iter;
317 }
318 
ForEach(JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,const JSHandle<JSTaggedValue> & callbackFn,const JSHandle<JSTaggedValue> & thisArg)319 JSTaggedValue JSAPILightWeightSet::ForEach(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
320                                            const JSHandle<JSTaggedValue> &callbackFn,
321                                            const JSHandle<JSTaggedValue> &thisArg)
322 {
323     JSHandle<JSAPILightWeightSet> lightweightset = JSHandle<JSAPILightWeightSet>::Cast(thisHandle);
324     CheckAndCopyValues(thread, lightweightset);
325     uint32_t length = lightweightset->GetSize();
326     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
327     for (uint32_t k = 0; k < length; k++) {
328         JSTaggedValue kValue = lightweightset->GetValueAt(k);
329         EcmaRuntimeCallInfo *info =
330             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, 3); // 3:three args
331         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
332         info->SetCallArg(kValue, kValue, thisHandle.GetTaggedValue());
333         JSTaggedValue funcResult = JSFunction::Call(info);
334         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
335         if (lightweightset->GetSize() != length) {  // prevent length change
336             length = lightweightset->GetSize();
337         }
338     }
339     return JSTaggedValue::Undefined();
340 }
341 
GetIndexOf(const JSThread * thread,JSHandle<JSTaggedValue> & value)342 int32_t JSAPILightWeightSet::GetIndexOf(const JSThread *thread, JSHandle<JSTaggedValue> &value)
343 {
344     uint32_t size = GetLength();
345     int32_t index = GetHashIndex(thread, value, size);
346     return index;
347 }
348 
Remove(JSThread * thread,JSHandle<JSTaggedValue> & value)349 JSTaggedValue JSAPILightWeightSet::Remove(JSThread *thread, JSHandle<JSTaggedValue> &value)
350 {
351     uint32_t size = GetLength();
352     TaggedArray *valueArray = TaggedArray::Cast(GetValues().GetTaggedObject());
353     int32_t index = GetHashIndex(thread, value, size);
354     if (index < 0) {
355         return JSTaggedValue::Undefined();
356     }
357     JSTaggedValue result = valueArray->Get(index);
358     RemoveAt(thread, index);
359     return result;
360 }
361 
RemoveAt(JSThread * thread,int32_t index)362 bool JSAPILightWeightSet::RemoveAt(JSThread *thread, int32_t index)
363 {
364     uint32_t size = GetLength();
365     if (index < 0 || index >= static_cast<int32_t>(size)) {
366         return false;
367     }
368     JSHandle<TaggedArray> valueArray(thread, GetValues());
369     JSHandle<TaggedArray> hashArray(thread, GetHashes());
370     RemoveValue(thread, hashArray, static_cast<uint32_t>(index));
371     RemoveValue(thread, valueArray, static_cast<uint32_t>(index));
372     SetLength(size - 1);
373     return true;
374 }
375 
RemoveValue(const JSThread * thread,JSHandle<TaggedArray> & taggedArray,uint32_t index)376 void JSAPILightWeightSet::RemoveValue(const JSThread *thread, JSHandle<TaggedArray> &taggedArray,
377                                       uint32_t index)
378 {
379     uint32_t len = GetLength();
380     ASSERT(index < len);
381     TaggedArray::RemoveElementByIndex(thread, taggedArray, index, len);
382 }
383 
AdjustArray(JSThread * thread,JSHandle<TaggedArray> srcArray,uint32_t fromIndex,uint32_t toIndex,bool direction)384 void JSAPILightWeightSet::AdjustArray(JSThread *thread, JSHandle<TaggedArray> srcArray, uint32_t fromIndex,
385                                       uint32_t toIndex, bool direction)
386 {
387     uint32_t size = GetLength();
388     uint32_t idx = size - 1;
389     if (direction) {
390         while (fromIndex < toIndex) {
391             JSTaggedValue value = srcArray->Get(idx);
392             srcArray->Set(thread, idx + 1, value);
393             idx--;
394             fromIndex++;
395         }
396     } else {
397         uint32_t moveSize = size - fromIndex;
398         for (uint32_t i = 0; i < moveSize; i++) {
399             if ((fromIndex + i) < size) {
400                 JSTaggedValue value = srcArray->Get(fromIndex + i);
401                 srcArray->Set(thread, toIndex + i, value);
402             } else {
403                 srcArray->Set(thread, toIndex + i, JSTaggedValue::Hole());
404             }
405         }
406     }
407 }
408 
ToString(JSThread * thread,const JSHandle<JSAPILightWeightSet> & obj)409 JSTaggedValue JSAPILightWeightSet::ToString(JSThread *thread, const JSHandle<JSAPILightWeightSet> &obj)
410 {
411     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
412     std::u16string sepStr = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(",");
413 
414     uint32_t length = obj->GetSize();
415     JSHandle<TaggedArray> valueArray(thread, obj->GetValues());
416     std::u16string concatStr;
417     JSMutableHandle<JSTaggedValue> values(thread, JSTaggedValue::Undefined());
418     for (uint32_t k = 0; k < length; k++) {
419         std::u16string nextStr;
420         values.Update(valueArray->Get(k));
421         if (!values->IsUndefined() && !values->IsNull()) {
422             JSHandle<EcmaString> nextStringHandle = JSTaggedValue::ToString(thread, values);
423             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
424             nextStr = EcmaStringAccessor(nextStringHandle).ToU16String();
425         }
426         if (k > 0) {
427             concatStr.append(sepStr);
428             concatStr.append(nextStr);
429             continue;
430         }
431         concatStr.append(nextStr);
432     }
433     char16_t *char16tData = concatStr.data();
434     auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData);
435     int32_t u16strSize = concatStr.size();
436     return factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue();
437 }
438 
Clear(JSThread * thread)439 void JSAPILightWeightSet::Clear(JSThread *thread)
440 {
441     TaggedArray *hashArray = TaggedArray::Cast(GetHashes().GetTaggedObject());
442     TaggedArray *valueArray = TaggedArray::Cast(GetValues().GetTaggedObject());
443     uint32_t size = GetLength();
444     for (uint32_t index = 0; index < size; index++) {
445         hashArray->Set(thread, index, JSTaggedValue::Hole());
446         valueArray->Set(thread, index, JSTaggedValue::Hole());
447     }
448     SetLength(0);
449 }
450 
Hash(const JSThread * thread,JSTaggedValue key)451 uint32_t JSAPILightWeightSet::Hash(const JSThread *thread, JSTaggedValue key)
452 {
453     if (key.IsDouble() && key.GetDouble() == 0.0) {
454         key = JSTaggedValue(0);
455     }
456     if (key.IsSymbol()) {
457         auto symbolString = JSSymbol::Cast(key.GetTaggedObject());
458         return symbolString->GetHashField();
459     }
460     if (key.IsString()) {
461         auto keyString = EcmaString::Cast(key.GetTaggedObject());
462         return EcmaStringAccessor(keyString).GetHashcode();
463     }
464     if (key.IsECMAObject()) {
465         uint32_t hash = ECMAObject::Cast(key.GetTaggedObject())->GetHash();
466         if (hash == 0) {
467             hash = static_cast<uint32_t>(base::RandomGenerator::GenerateIdentityHash());
468             JSHandle<ECMAObject> ecmaObj(thread, key);
469             ECMAObject::SetHash(thread, hash, ecmaObj);
470         }
471         return hash;
472     }
473     if (key.IsInt()) {
474         uint32_t hash = static_cast<uint32_t>(key.GetInt());
475         return hash;
476     }
477     uint64_t keyValue = key.GetRawData();
478     return GetHash32(reinterpret_cast<uint8_t *>(&keyValue), sizeof(keyValue) / sizeof(uint8_t));
479 }
480 
CheckAndCopyValues(const JSThread * thread,JSHandle<JSAPILightWeightSet> obj)481 void JSAPILightWeightSet::CheckAndCopyValues(const JSThread *thread, JSHandle<JSAPILightWeightSet> obj)
482 {
483     JSHandle<TaggedArray> values(thread, obj->GetValues());
484     // Check whether array is shared in the nonmovable space before set properties and elements.
485     // If true, then really copy array in the semi space.
486     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
487     if (values.GetTaggedValue().IsCOWArray()) {
488         auto newArray = factory->CopyArray(values, values->GetLength(), values->GetLength(),
489             JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
490         obj->SetValues(thread, newArray.GetTaggedValue());
491     }
492 }
493 } // namespace panda::ecmascript
494