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#include "ecmascript/weak_vector.h" 17 18#include "ecmascript/object_factory.h" 19 20namespace panda::ecmascript { 21JSHandle<WeakVector> WeakVector::Create(const JSThread *thread, uint32_t capacity, MemSpaceType type) 22{ 23 ASSERT(capacity < MAX_VECTOR_INDEX); 24 25 uint32_t length = VectorToArrayIndex(capacity); 26 JSHandle<WeakVector> vector; 27 if (type == MemSpaceType::NON_MOVABLE) { 28 vector = JSHandle<WeakVector>(thread->GetEcmaVM()->GetFactory() 29 ->NewTaggedArray(length, JSTaggedValue::Hole(), MemSpaceType::NON_MOVABLE)); 30 } else { 31 vector = JSHandle<WeakVector>(thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length)); 32 } 33 34 vector->SetEnd(thread, 0); 35 return vector; 36} 37 38bool WeakVector::Delete(const JSThread *thread, uint32_t index) 39{ 40 uint32_t end = GetEnd(); 41 if (index < end) { 42 Set(thread, index, JSTaggedValue::Hole()); 43 return true; 44 } 45 return false; 46} 47 48JSHandle<WeakVector> WeakVector::Grow(const JSThread *thread, const JSHandle<WeakVector> &old, uint32_t newCapacity) 49{ 50 uint32_t oldCapacity = old->GetCapacity(); 51 ASSERT(newCapacity > oldCapacity); 52 if (oldCapacity == MAX_VECTOR_INDEX) { 53 return old; 54 } 55 56 if (newCapacity > MAX_VECTOR_INDEX) { 57 newCapacity = MAX_VECTOR_INDEX; 58 } 59 60 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 61 JSHandle<TaggedArray> newVec = factory->CopyArray(JSHandle<TaggedArray>(old), VectorToArrayIndex(oldCapacity), 62 VectorToArrayIndex(newCapacity)); 63 64 return JSHandle<WeakVector>(newVec); 65} 66 67JSHandle<WeakVector> WeakVector::Append(const JSThread *thread, const JSHandle<WeakVector> &vec, 68 const JSHandle<JSTaggedValue> &value, ElementType type) 69{ 70 if (!vec->Full()) { 71 JSTaggedValue storeVal = GetStoreVal(value, type); 72 vec->PushBack(thread, storeVal); 73 return vec; 74 } 75 76 return AppendToFullVec(thread, vec, value, type); 77} 78 79JSHandle<WeakVector> WeakVector::FillOrAppend(const JSThread *thread, const JSHandle<WeakVector> &vec, 80 const JSHandle<JSTaggedValue> &value, ElementType type) 81{ 82 if (!vec->Full()) { 83 JSTaggedValue storeVal = GetStoreVal(value, type); 84 vec->PushBack(thread, storeVal); 85 return vec; 86 } 87 88 // if exist hole, use it. 89 uint32_t holeIndex = CheckHole(vec); 90 if (holeIndex != TaggedArray::MAX_ARRAY_INDEX) { 91 JSTaggedValue storeVal = GetStoreVal(value, type); 92 vec->Set(thread, holeIndex, storeVal); 93 return vec; 94 } 95 96 return AppendToFullVec(thread, vec, value, type); 97} 98 99JSHandle<WeakVector> WeakVector::AppendToFullVec(const JSThread *thread, const JSHandle<WeakVector> &vec, 100 const JSHandle<JSTaggedValue> &value, ElementType type) 101{ 102 uint32_t newCapacity = vec->GetCapacity() + DEFAULT_GROW_SIZE; 103 JSHandle<WeakVector> newVec = WeakVector::Grow(thread, JSHandle<WeakVector>(vec), newCapacity); 104 JSTaggedValue storeVal = GetStoreVal(value, type); 105 [[maybe_unused]] uint32_t index = newVec->PushBack(thread, storeVal); 106 ASSERT(index != TaggedArray::MAX_ARRAY_INDEX); 107 return newVec; 108} 109 110JSTaggedValue WeakVector::GetStoreVal(const JSHandle<JSTaggedValue> &value, ElementType type) 111{ 112 if (type == ElementType::NORMAL) { 113 return value.GetTaggedValue(); 114 } 115 116 if (value->IsHeapObject()) { 117 return value->CreateAndGetWeakRef(); 118 } 119 return value.GetTaggedValue(); 120} 121 122JSHandle<WeakVector> WeakVector::Copy(const JSThread *thread, const JSHandle<WeakVector> &vec, 123 bool needExtend) 124{ 125 uint32_t capacity = vec->GetCapacity(); 126 uint32_t oldLength = VectorToArrayIndex(capacity); 127 if (needExtend) { 128 capacity += DEFAULT_GROW_SIZE; 129 } 130 uint32_t newLength = VectorToArrayIndex(capacity); 131 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 132 JSHandle<TaggedArray> newVec = factory->CopyArray(JSHandle<TaggedArray>(vec), oldLength, newLength); 133 return JSHandle<WeakVector>(newVec); 134} 135 136uint32_t WeakVector::CheckHole(const JSHandle<WeakVector> &vec) 137{ 138 for (uint32_t i = 0; i < vec->GetEnd(); i++) { 139 JSTaggedValue value = vec->Get(i); 140 if (value.IsHole()) { 141 return i; 142 } 143 } 144 return TaggedArray::MAX_ARRAY_INDEX; 145} 146 147uint32_t WeakVector::PushBack(const JSThread *thread, JSTaggedValue value) 148{ 149 uint32_t end = GetEnd(); 150 if (end == GetCapacity()) { 151 return TaggedArray::MAX_ARRAY_INDEX; 152 } 153 154 Set(thread, end, value); 155 SetEnd(thread, end + 1); 156 return end; 157} 158} // namespace panda::ecmascript 159