14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/weak_vector.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/object_factory.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_cinamespace panda::ecmascript {
214514f5e3Sopenharmony_ciJSHandle<WeakVector> WeakVector::Create(const JSThread *thread, uint32_t capacity, MemSpaceType type)
224514f5e3Sopenharmony_ci{
234514f5e3Sopenharmony_ci    ASSERT(capacity < MAX_VECTOR_INDEX);
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_ci    uint32_t length = VectorToArrayIndex(capacity);
264514f5e3Sopenharmony_ci    JSHandle<WeakVector> vector;
274514f5e3Sopenharmony_ci    if (type == MemSpaceType::NON_MOVABLE) {
284514f5e3Sopenharmony_ci        vector = JSHandle<WeakVector>(thread->GetEcmaVM()->GetFactory()
294514f5e3Sopenharmony_ci                                      ->NewTaggedArray(length, JSTaggedValue::Hole(), MemSpaceType::NON_MOVABLE));
304514f5e3Sopenharmony_ci    } else {
314514f5e3Sopenharmony_ci        vector = JSHandle<WeakVector>(thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length));
324514f5e3Sopenharmony_ci    }
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ci    vector->SetEnd(thread, 0);
354514f5e3Sopenharmony_ci    return vector;
364514f5e3Sopenharmony_ci}
374514f5e3Sopenharmony_ci
384514f5e3Sopenharmony_cibool WeakVector::Delete(const JSThread *thread, uint32_t index)
394514f5e3Sopenharmony_ci{
404514f5e3Sopenharmony_ci    uint32_t end = GetEnd();
414514f5e3Sopenharmony_ci    if (index < end) {
424514f5e3Sopenharmony_ci        Set(thread, index, JSTaggedValue::Hole());
434514f5e3Sopenharmony_ci        return true;
444514f5e3Sopenharmony_ci    }
454514f5e3Sopenharmony_ci    return false;
464514f5e3Sopenharmony_ci}
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ciJSHandle<WeakVector> WeakVector::Grow(const JSThread *thread, const JSHandle<WeakVector> &old, uint32_t newCapacity)
494514f5e3Sopenharmony_ci{
504514f5e3Sopenharmony_ci    uint32_t oldCapacity = old->GetCapacity();
514514f5e3Sopenharmony_ci    ASSERT(newCapacity > oldCapacity);
524514f5e3Sopenharmony_ci    if (oldCapacity == MAX_VECTOR_INDEX) {
534514f5e3Sopenharmony_ci        return old;
544514f5e3Sopenharmony_ci    }
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ci    if (newCapacity > MAX_VECTOR_INDEX) {
574514f5e3Sopenharmony_ci        newCapacity = MAX_VECTOR_INDEX;
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
614514f5e3Sopenharmony_ci    JSHandle<TaggedArray> newVec = factory->CopyArray(JSHandle<TaggedArray>(old), VectorToArrayIndex(oldCapacity),
624514f5e3Sopenharmony_ci                                                      VectorToArrayIndex(newCapacity));
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_ci    return JSHandle<WeakVector>(newVec);
654514f5e3Sopenharmony_ci}
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_ciJSHandle<WeakVector> WeakVector::Append(const JSThread *thread, const JSHandle<WeakVector> &vec,
684514f5e3Sopenharmony_ci                                        const JSHandle<JSTaggedValue> &value, ElementType type)
694514f5e3Sopenharmony_ci{
704514f5e3Sopenharmony_ci    if (!vec->Full()) {
714514f5e3Sopenharmony_ci        JSTaggedValue storeVal = GetStoreVal(value, type);
724514f5e3Sopenharmony_ci        vec->PushBack(thread, storeVal);
734514f5e3Sopenharmony_ci        return vec;
744514f5e3Sopenharmony_ci    }
754514f5e3Sopenharmony_ci
764514f5e3Sopenharmony_ci    return AppendToFullVec(thread, vec, value, type);
774514f5e3Sopenharmony_ci}
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_ciJSHandle<WeakVector> WeakVector::FillOrAppend(const JSThread *thread, const JSHandle<WeakVector> &vec,
804514f5e3Sopenharmony_ci                                              const JSHandle<JSTaggedValue> &value, ElementType type)
814514f5e3Sopenharmony_ci{
824514f5e3Sopenharmony_ci    if (!vec->Full()) {
834514f5e3Sopenharmony_ci        JSTaggedValue storeVal = GetStoreVal(value, type);
844514f5e3Sopenharmony_ci        vec->PushBack(thread, storeVal);
854514f5e3Sopenharmony_ci        return vec;
864514f5e3Sopenharmony_ci    }
874514f5e3Sopenharmony_ci
884514f5e3Sopenharmony_ci    // if exist hole, use it.
894514f5e3Sopenharmony_ci    uint32_t holeIndex = CheckHole(vec);
904514f5e3Sopenharmony_ci    if (holeIndex != TaggedArray::MAX_ARRAY_INDEX) {
914514f5e3Sopenharmony_ci        JSTaggedValue storeVal = GetStoreVal(value, type);
924514f5e3Sopenharmony_ci        vec->Set(thread, holeIndex, storeVal);
934514f5e3Sopenharmony_ci        return vec;
944514f5e3Sopenharmony_ci    }
954514f5e3Sopenharmony_ci
964514f5e3Sopenharmony_ci    return AppendToFullVec(thread, vec, value, type);
974514f5e3Sopenharmony_ci}
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_ciJSHandle<WeakVector> WeakVector::AppendToFullVec(const JSThread *thread, const JSHandle<WeakVector> &vec,
1004514f5e3Sopenharmony_ci                                                 const JSHandle<JSTaggedValue> &value, ElementType type)
1014514f5e3Sopenharmony_ci{
1024514f5e3Sopenharmony_ci    uint32_t newCapacity = vec->GetCapacity() + DEFAULT_GROW_SIZE;
1034514f5e3Sopenharmony_ci    JSHandle<WeakVector> newVec = WeakVector::Grow(thread, JSHandle<WeakVector>(vec), newCapacity);
1044514f5e3Sopenharmony_ci    JSTaggedValue storeVal = GetStoreVal(value, type);
1054514f5e3Sopenharmony_ci    [[maybe_unused]] uint32_t index = newVec->PushBack(thread, storeVal);
1064514f5e3Sopenharmony_ci    ASSERT(index != TaggedArray::MAX_ARRAY_INDEX);
1074514f5e3Sopenharmony_ci    return newVec;
1084514f5e3Sopenharmony_ci}
1094514f5e3Sopenharmony_ci
1104514f5e3Sopenharmony_ciJSTaggedValue WeakVector::GetStoreVal(const JSHandle<JSTaggedValue> &value, ElementType type)
1114514f5e3Sopenharmony_ci{
1124514f5e3Sopenharmony_ci    if (type == ElementType::NORMAL) {
1134514f5e3Sopenharmony_ci        return value.GetTaggedValue();
1144514f5e3Sopenharmony_ci    }
1154514f5e3Sopenharmony_ci
1164514f5e3Sopenharmony_ci    if (value->IsHeapObject()) {
1174514f5e3Sopenharmony_ci        return value->CreateAndGetWeakRef();
1184514f5e3Sopenharmony_ci    }
1194514f5e3Sopenharmony_ci    return value.GetTaggedValue();
1204514f5e3Sopenharmony_ci}
1214514f5e3Sopenharmony_ci
1224514f5e3Sopenharmony_ciJSHandle<WeakVector> WeakVector::Copy(const JSThread *thread, const JSHandle<WeakVector> &vec,
1234514f5e3Sopenharmony_ci                                      bool needExtend)
1244514f5e3Sopenharmony_ci{
1254514f5e3Sopenharmony_ci    uint32_t capacity = vec->GetCapacity();
1264514f5e3Sopenharmony_ci    uint32_t oldLength = VectorToArrayIndex(capacity);
1274514f5e3Sopenharmony_ci    if (needExtend) {
1284514f5e3Sopenharmony_ci        capacity += DEFAULT_GROW_SIZE;
1294514f5e3Sopenharmony_ci    }
1304514f5e3Sopenharmony_ci    uint32_t newLength = VectorToArrayIndex(capacity);
1314514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1324514f5e3Sopenharmony_ci    JSHandle<TaggedArray> newVec = factory->CopyArray(JSHandle<TaggedArray>(vec), oldLength, newLength);
1334514f5e3Sopenharmony_ci    return JSHandle<WeakVector>(newVec);
1344514f5e3Sopenharmony_ci}
1354514f5e3Sopenharmony_ci
1364514f5e3Sopenharmony_ciuint32_t WeakVector::CheckHole(const JSHandle<WeakVector> &vec)
1374514f5e3Sopenharmony_ci{
1384514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < vec->GetEnd(); i++) {
1394514f5e3Sopenharmony_ci        JSTaggedValue value = vec->Get(i);
1404514f5e3Sopenharmony_ci        if (value.IsHole()) {
1414514f5e3Sopenharmony_ci            return i;
1424514f5e3Sopenharmony_ci        }
1434514f5e3Sopenharmony_ci    }
1444514f5e3Sopenharmony_ci    return TaggedArray::MAX_ARRAY_INDEX;
1454514f5e3Sopenharmony_ci}
1464514f5e3Sopenharmony_ci
1474514f5e3Sopenharmony_ciuint32_t WeakVector::PushBack(const JSThread *thread, JSTaggedValue value)
1484514f5e3Sopenharmony_ci{
1494514f5e3Sopenharmony_ci    uint32_t end = GetEnd();
1504514f5e3Sopenharmony_ci    if (end == GetCapacity()) {
1514514f5e3Sopenharmony_ci        return TaggedArray::MAX_ARRAY_INDEX;
1524514f5e3Sopenharmony_ci    }
1534514f5e3Sopenharmony_ci
1544514f5e3Sopenharmony_ci    Set(thread, end, value);
1554514f5e3Sopenharmony_ci    SetEnd(thread, end + 1);
1564514f5e3Sopenharmony_ci    return end;
1574514f5e3Sopenharmony_ci}
1584514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
159