14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 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/mem/free_object_list.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/free_object.h" 194514f5e3Sopenharmony_ci#include "ecmascript/mem/jit_fort.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_cinamespace panda::ecmascript { 224514f5e3Sopenharmony_citemplate <typename T> 234514f5e3Sopenharmony_ciFreeObjectList<T>::FreeObjectList(JitFort * fort) : sets_(new FreeObjectSet<T> *[NUMBER_OF_SETS](), NUMBER_OF_SETS), 244514f5e3Sopenharmony_ci lastSets_(new FreeObjectSet<T> *[NUMBER_OF_SETS](), NUMBER_OF_SETS), jitFort_(fort) 254514f5e3Sopenharmony_ci{ 264514f5e3Sopenharmony_ci for (int i = 0; i < NUMBER_OF_SETS; i++) { 274514f5e3Sopenharmony_ci sets_[i] = nullptr; 284514f5e3Sopenharmony_ci lastSets_[i] = nullptr; 294514f5e3Sopenharmony_ci } 304514f5e3Sopenharmony_ci noneEmptySetBitMap_ = 0; 314514f5e3Sopenharmony_ci} 324514f5e3Sopenharmony_citemplate FreeObjectList<FreeObject>::FreeObjectList(JitFort* fort); 334514f5e3Sopenharmony_citemplate FreeObjectList<MemDesc>::FreeObjectList(JitFort* fort); 344514f5e3Sopenharmony_ci 354514f5e3Sopenharmony_citemplate <typename T> 364514f5e3Sopenharmony_ciFreeObjectList<T>::~FreeObjectList() 374514f5e3Sopenharmony_ci{ 384514f5e3Sopenharmony_ci delete[] sets_.data(); 394514f5e3Sopenharmony_ci delete[] lastSets_.data(); 404514f5e3Sopenharmony_ci noneEmptySetBitMap_ = 0; 414514f5e3Sopenharmony_ci} 424514f5e3Sopenharmony_citemplate FreeObjectList<FreeObject>::~FreeObjectList(); 434514f5e3Sopenharmony_citemplate FreeObjectList<MemDesc>::~FreeObjectList(); 444514f5e3Sopenharmony_ci 454514f5e3Sopenharmony_citemplate <typename T> 464514f5e3Sopenharmony_ciT *FreeObjectList<T>::Allocate(size_t size) 474514f5e3Sopenharmony_ci{ 484514f5e3Sopenharmony_ci if (noneEmptySetBitMap_ == 0) { 494514f5e3Sopenharmony_ci return nullptr; 504514f5e3Sopenharmony_ci } 514514f5e3Sopenharmony_ci // find from suitable 524514f5e3Sopenharmony_ci SetType type = SelectSetType(size); 534514f5e3Sopenharmony_ci if (type == FreeObjectSet<T>::INVALID_SET_TYPE) { 544514f5e3Sopenharmony_ci return nullptr; 554514f5e3Sopenharmony_ci } 564514f5e3Sopenharmony_ci 574514f5e3Sopenharmony_ci SetType lastType = type - 1; 584514f5e3Sopenharmony_ci for (type = static_cast<int32_t>(CalcNextNoneEmptyIndex(type)); type > lastType && type < NUMBER_OF_SETS; 594514f5e3Sopenharmony_ci type = static_cast<int32_t>(CalcNextNoneEmptyIndex(type + 1))) { 604514f5e3Sopenharmony_ci lastType = type; 614514f5e3Sopenharmony_ci FreeObjectSet<T> *current = sets_[type]; 624514f5e3Sopenharmony_ci while (current != nullptr) { 634514f5e3Sopenharmony_ci if (current->Available() < size) { 644514f5e3Sopenharmony_ci current = current->next_; 654514f5e3Sopenharmony_ci continue; 664514f5e3Sopenharmony_ci } 674514f5e3Sopenharmony_ci FreeObjectSet<T> *next = nullptr; 684514f5e3Sopenharmony_ci T *object = T::Cast(INVALID_OBJPTR); 694514f5e3Sopenharmony_ci if (type <= SMALL_SET_MAX_INDEX) { 704514f5e3Sopenharmony_ci object = current->ObtainSmallFreeObject(size); 714514f5e3Sopenharmony_ci } else { 724514f5e3Sopenharmony_ci next = current->next_; 734514f5e3Sopenharmony_ci object = current->ObtainLargeFreeObject(size); 744514f5e3Sopenharmony_ci } 754514f5e3Sopenharmony_ci if (current->Empty()) { 764514f5e3Sopenharmony_ci RemoveSet(current); 774514f5e3Sopenharmony_ci current->Rebuild(); 784514f5e3Sopenharmony_ci } 794514f5e3Sopenharmony_ci if (object != T::Cast(INVALID_OBJPTR)) { 804514f5e3Sopenharmony_ci available_ -= object->Available(); 814514f5e3Sopenharmony_ci return object; 824514f5e3Sopenharmony_ci } 834514f5e3Sopenharmony_ci current = next; 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci } 864514f5e3Sopenharmony_ci return nullptr; 874514f5e3Sopenharmony_ci} 884514f5e3Sopenharmony_citemplate FreeObject *FreeObjectList<FreeObject>::Allocate(size_t size); 894514f5e3Sopenharmony_citemplate MemDesc *FreeObjectList<MemDesc>::Allocate(size_t size); 904514f5e3Sopenharmony_ci 914514f5e3Sopenharmony_citemplate <typename T> 924514f5e3Sopenharmony_ciT *FreeObjectList<T>::LookupSuitableFreeObject(size_t size) 934514f5e3Sopenharmony_ci{ 944514f5e3Sopenharmony_ci if (noneEmptySetBitMap_ == 0) { 954514f5e3Sopenharmony_ci return nullptr; 964514f5e3Sopenharmony_ci } 974514f5e3Sopenharmony_ci // find a suitable type 984514f5e3Sopenharmony_ci SetType type = SelectSetType(size); 994514f5e3Sopenharmony_ci if (type == FreeObjectSet<T>::INVALID_SET_TYPE) { 1004514f5e3Sopenharmony_ci return nullptr; 1014514f5e3Sopenharmony_ci } 1024514f5e3Sopenharmony_ci 1034514f5e3Sopenharmony_ci SetType lastType = type - 1; 1044514f5e3Sopenharmony_ci for (type = static_cast<int32_t>(CalcNextNoneEmptyIndex(type)); type > lastType && type < NUMBER_OF_SETS; 1054514f5e3Sopenharmony_ci type = static_cast<int32_t>(CalcNextNoneEmptyIndex(type + 1))) { 1064514f5e3Sopenharmony_ci lastType = type; 1074514f5e3Sopenharmony_ci FreeObjectSet<T> *current = sets_[type]; 1084514f5e3Sopenharmony_ci while (current != nullptr) { 1094514f5e3Sopenharmony_ci FreeObjectSet<T> *next = nullptr; 1104514f5e3Sopenharmony_ci T *object = INVALID_OBJECT; 1114514f5e3Sopenharmony_ci if (type <= SMALL_SET_MAX_INDEX) { 1124514f5e3Sopenharmony_ci object = current->LookupSmallFreeObject(size); 1134514f5e3Sopenharmony_ci } else { 1144514f5e3Sopenharmony_ci next = current->next_; 1154514f5e3Sopenharmony_ci object = current->LookupLargeFreeObject(size); 1164514f5e3Sopenharmony_ci } 1174514f5e3Sopenharmony_ci if (object != INVALID_OBJECT) { 1184514f5e3Sopenharmony_ci return object; 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci current = next; 1214514f5e3Sopenharmony_ci } 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci return nullptr; 1244514f5e3Sopenharmony_ci} 1254514f5e3Sopenharmony_citemplate FreeObject *FreeObjectList<FreeObject>::LookupSuitableFreeObject(size_t); 1264514f5e3Sopenharmony_ci 1274514f5e3Sopenharmony_citemplate <typename T> 1284514f5e3Sopenharmony_citemplate <typename U> 1294514f5e3Sopenharmony_civoid FreeObjectList<T>::FreeImpl(U* region, uintptr_t start, size_t size, bool isAdd) 1304514f5e3Sopenharmony_ci{ 1314514f5e3Sopenharmony_ci if (UNLIKELY(start == 0)) { 1324514f5e3Sopenharmony_ci return; 1334514f5e3Sopenharmony_ci } 1344514f5e3Sopenharmony_ci if (UNLIKELY(size < MIN_SIZE)) { 1354514f5e3Sopenharmony_ci region->IncreaseWasted(size); 1364514f5e3Sopenharmony_ci if (isAdd) { 1374514f5e3Sopenharmony_ci wasted_ += size; 1384514f5e3Sopenharmony_ci } 1394514f5e3Sopenharmony_ci return; 1404514f5e3Sopenharmony_ci } 1414514f5e3Sopenharmony_ci 1424514f5e3Sopenharmony_ci SetType type = SelectSetType(size); 1434514f5e3Sopenharmony_ci if (type == FreeObjectSet<T>::INVALID_SET_TYPE) { 1444514f5e3Sopenharmony_ci return; 1454514f5e3Sopenharmony_ci } 1464514f5e3Sopenharmony_ci 1474514f5e3Sopenharmony_ci auto set = region->GetFreeObjectSet(type); 1484514f5e3Sopenharmony_ci if (set == nullptr) { 1494514f5e3Sopenharmony_ci LOG_FULL(FATAL) << "The set of region is nullptr"; 1504514f5e3Sopenharmony_ci return; 1514514f5e3Sopenharmony_ci } 1524514f5e3Sopenharmony_ci set->Free(start, size); 1534514f5e3Sopenharmony_ci 1544514f5e3Sopenharmony_ci if (isAdd) { 1554514f5e3Sopenharmony_ci if (set->isAdded_ == 0) { 1564514f5e3Sopenharmony_ci AddSet(set); 1574514f5e3Sopenharmony_ci } else { 1584514f5e3Sopenharmony_ci available_ += size; 1594514f5e3Sopenharmony_ci } 1604514f5e3Sopenharmony_ci } 1614514f5e3Sopenharmony_ci} 1624514f5e3Sopenharmony_citemplate void FreeObjectList<FreeObject>::FreeImpl<Region>(Region* region, uintptr_t start, size_t size, bool isAdd); 1634514f5e3Sopenharmony_citemplate void FreeObjectList<MemDesc>::FreeImpl<JitFortRegion>(JitFortRegion* region, 1644514f5e3Sopenharmony_ci uintptr_t start, size_t size, bool isAdd); 1654514f5e3Sopenharmony_ci 1664514f5e3Sopenharmony_citemplate <typename T> 1674514f5e3Sopenharmony_civoid FreeObjectList<T>::Free(uintptr_t start, size_t size, bool isAdd) 1684514f5e3Sopenharmony_ci{ 1694514f5e3Sopenharmony_ci return FreeImpl<Region>(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(start)), start, size, isAdd); 1704514f5e3Sopenharmony_ci} 1714514f5e3Sopenharmony_ci 1724514f5e3Sopenharmony_ci// template class instance for non JitFort space uses FreeObject and Region. 1734514f5e3Sopenharmony_citemplate void FreeObjectList<FreeObject>::Free(uintptr_t, size_t, bool); 1744514f5e3Sopenharmony_ci// template class instance for JitFort space uses MemDesc and JitFortRegion 1754514f5e3Sopenharmony_citemplate <> 1764514f5e3Sopenharmony_civoid FreeObjectList<MemDesc>::Free(uintptr_t start, size_t size, bool isAdd) 1774514f5e3Sopenharmony_ci{ 1784514f5e3Sopenharmony_ci return FreeImpl<JitFortRegion>(jitFort_->ObjectAddressToRange(start), start, size, isAdd); 1794514f5e3Sopenharmony_ci} 1804514f5e3Sopenharmony_ci 1814514f5e3Sopenharmony_citemplate <typename T> 1824514f5e3Sopenharmony_civoid FreeObjectList<T>::Rebuild() 1834514f5e3Sopenharmony_ci{ 1844514f5e3Sopenharmony_ci EnumerateSets([](FreeObjectSet<T> *set) { set->Rebuild(); }); 1854514f5e3Sopenharmony_ci for (int i = 0; i < NUMBER_OF_SETS; i++) { 1864514f5e3Sopenharmony_ci sets_[i] = nullptr; 1874514f5e3Sopenharmony_ci lastSets_[i] = nullptr; 1884514f5e3Sopenharmony_ci } 1894514f5e3Sopenharmony_ci available_ = 0; 1904514f5e3Sopenharmony_ci wasted_ = 0; 1914514f5e3Sopenharmony_ci noneEmptySetBitMap_ = 0; 1924514f5e3Sopenharmony_ci} 1934514f5e3Sopenharmony_citemplate void FreeObjectList<FreeObject>::Rebuild(); 1944514f5e3Sopenharmony_citemplate void FreeObjectList<MemDesc>::Rebuild(); 1954514f5e3Sopenharmony_ci 1964514f5e3Sopenharmony_citemplate <typename T> 1974514f5e3Sopenharmony_cibool FreeObjectList<T>::MatchFreeObjectInSet(FreeObjectSet<T> *set, size_t size) 1984514f5e3Sopenharmony_ci{ 1994514f5e3Sopenharmony_ci if (set == nullptr || set->Empty()) { 2004514f5e3Sopenharmony_ci return false; 2014514f5e3Sopenharmony_ci } 2024514f5e3Sopenharmony_ci // find a suitable type 2034514f5e3Sopenharmony_ci SetType type = SelectSetType(size); 2044514f5e3Sopenharmony_ci if (type == FreeObjectSet<T>::INVALID_SET_TYPE) { 2054514f5e3Sopenharmony_ci return false; 2064514f5e3Sopenharmony_ci } 2074514f5e3Sopenharmony_ci 2084514f5e3Sopenharmony_ci T *object = nullptr; 2094514f5e3Sopenharmony_ci if (type <= SMALL_SET_MAX_INDEX) { 2104514f5e3Sopenharmony_ci object = set->LookupSmallFreeObject(size); 2114514f5e3Sopenharmony_ci } else { 2124514f5e3Sopenharmony_ci object = set->LookupLargeFreeObject(size); 2134514f5e3Sopenharmony_ci } 2144514f5e3Sopenharmony_ci return object != nullptr; 2154514f5e3Sopenharmony_ci} 2164514f5e3Sopenharmony_citemplate bool FreeObjectList<FreeObject>::MatchFreeObjectInSet(FreeObjectSet<FreeObject> *, size_t); 2174514f5e3Sopenharmony_ci 2184514f5e3Sopenharmony_citemplate <typename T> 2194514f5e3Sopenharmony_cibool FreeObjectList<T>::AddSet(FreeObjectSet<T> *set) 2204514f5e3Sopenharmony_ci{ 2214514f5e3Sopenharmony_ci if (set == nullptr || set->Empty() || set->isAdded_ != 0) { 2224514f5e3Sopenharmony_ci return false; 2234514f5e3Sopenharmony_ci } 2244514f5e3Sopenharmony_ci SetType type = set->setType_; 2254514f5e3Sopenharmony_ci FreeObjectSet<T> *top = sets_[type]; 2264514f5e3Sopenharmony_ci if (set == top) { 2274514f5e3Sopenharmony_ci return false; 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci if (top != nullptr) { 2304514f5e3Sopenharmony_ci top->prev_ = set; 2314514f5e3Sopenharmony_ci } 2324514f5e3Sopenharmony_ci set->isAdded_ = 1; // 1: added 2334514f5e3Sopenharmony_ci set->next_ = top; 2344514f5e3Sopenharmony_ci set->prev_ = nullptr; 2354514f5e3Sopenharmony_ci if (lastSets_[type] == nullptr) { 2364514f5e3Sopenharmony_ci lastSets_[type] = set; 2374514f5e3Sopenharmony_ci } 2384514f5e3Sopenharmony_ci if (sets_[type] == nullptr) { 2394514f5e3Sopenharmony_ci SetNoneEmptyBit(type); 2404514f5e3Sopenharmony_ci } 2414514f5e3Sopenharmony_ci sets_[type] = set; 2424514f5e3Sopenharmony_ci available_ += set->Available(); 2434514f5e3Sopenharmony_ci return true; 2444514f5e3Sopenharmony_ci} 2454514f5e3Sopenharmony_citemplate bool FreeObjectList<FreeObject>::AddSet(FreeObjectSet<FreeObject> *); 2464514f5e3Sopenharmony_citemplate bool FreeObjectList<MemDesc>::AddSet(FreeObjectSet<MemDesc> *); 2474514f5e3Sopenharmony_ci 2484514f5e3Sopenharmony_citemplate <typename T> 2494514f5e3Sopenharmony_civoid FreeObjectList<T>::RemoveSet(FreeObjectSet<T> *set) 2504514f5e3Sopenharmony_ci{ 2514514f5e3Sopenharmony_ci if (set == nullptr) { 2524514f5e3Sopenharmony_ci return; 2534514f5e3Sopenharmony_ci } 2544514f5e3Sopenharmony_ci SetType type = set->setType_; 2554514f5e3Sopenharmony_ci FreeObjectSet<T> *top = sets_[type]; 2564514f5e3Sopenharmony_ci FreeObjectSet<T> *end = lastSets_[type]; 2574514f5e3Sopenharmony_ci if (top == set) { 2584514f5e3Sopenharmony_ci sets_[type] = top->next_; 2594514f5e3Sopenharmony_ci } 2604514f5e3Sopenharmony_ci if (end == set) { 2614514f5e3Sopenharmony_ci lastSets_[type] = end->prev_; 2624514f5e3Sopenharmony_ci } 2634514f5e3Sopenharmony_ci if (set->prev_ != nullptr) { 2644514f5e3Sopenharmony_ci set->prev_->next_ = set->next_; 2654514f5e3Sopenharmony_ci } 2664514f5e3Sopenharmony_ci if (set->next_ != nullptr) { 2674514f5e3Sopenharmony_ci set->next_->prev_ = set->prev_; 2684514f5e3Sopenharmony_ci } 2694514f5e3Sopenharmony_ci set->isAdded_ = 0; 2704514f5e3Sopenharmony_ci set->prev_ = nullptr; 2714514f5e3Sopenharmony_ci set->next_ = nullptr; 2724514f5e3Sopenharmony_ci if (sets_[type] == nullptr) { 2734514f5e3Sopenharmony_ci ClearNoneEmptyBit(type); 2744514f5e3Sopenharmony_ci } 2754514f5e3Sopenharmony_ci available_ -= set->Available(); 2764514f5e3Sopenharmony_ci} 2774514f5e3Sopenharmony_citemplate void FreeObjectList<FreeObject>::RemoveSet(FreeObjectSet<FreeObject> *); 2784514f5e3Sopenharmony_ci 2794514f5e3Sopenharmony_citemplate <typename T> 2804514f5e3Sopenharmony_civoid FreeObjectList<T>::Merge(FreeObjectList<T> *list) 2814514f5e3Sopenharmony_ci{ 2824514f5e3Sopenharmony_ci list->EnumerateTopAndLastSets([this](FreeObjectSet<T> *set, FreeObjectSet<T> *end) { 2834514f5e3Sopenharmony_ci if (set == nullptr || set->Empty()) { 2844514f5e3Sopenharmony_ci return; 2854514f5e3Sopenharmony_ci } 2864514f5e3Sopenharmony_ci SetType type = set->setType_; 2874514f5e3Sopenharmony_ci FreeObjectSet<T> *top = sets_[type]; 2884514f5e3Sopenharmony_ci if (top == nullptr) { 2894514f5e3Sopenharmony_ci top = set; 2904514f5e3Sopenharmony_ci } else { 2914514f5e3Sopenharmony_ci lastSets_[type]->next_ = set; 2924514f5e3Sopenharmony_ci set->prev_ = lastSets_[type]; 2934514f5e3Sopenharmony_ci } 2944514f5e3Sopenharmony_ci lastSets_[type] = end; 2954514f5e3Sopenharmony_ci SetNoneEmptyBit(type); 2964514f5e3Sopenharmony_ci }); 2974514f5e3Sopenharmony_ci available_ += list->available_; 2984514f5e3Sopenharmony_ci list->Rebuild(); 2994514f5e3Sopenharmony_ci} 3004514f5e3Sopenharmony_ci 3014514f5e3Sopenharmony_citemplate<typename T> 3024514f5e3Sopenharmony_citemplate<class Callback> 3034514f5e3Sopenharmony_civoid FreeObjectList<T>::EnumerateSets(const Callback &cb) const 3044514f5e3Sopenharmony_ci{ 3054514f5e3Sopenharmony_ci for (SetType i = 0; i < NUMBER_OF_SETS; i++) { 3064514f5e3Sopenharmony_ci EnumerateSets(i, cb); 3074514f5e3Sopenharmony_ci } 3084514f5e3Sopenharmony_ci} 3094514f5e3Sopenharmony_ci 3104514f5e3Sopenharmony_citemplate<typename T> 3114514f5e3Sopenharmony_citemplate<class Callback> 3124514f5e3Sopenharmony_civoid FreeObjectList<T>::EnumerateSets(SetType type, const Callback &cb) const 3134514f5e3Sopenharmony_ci{ 3144514f5e3Sopenharmony_ci FreeObjectSet<T> *current = sets_[type]; 3154514f5e3Sopenharmony_ci while (current != nullptr) { 3164514f5e3Sopenharmony_ci // maybe reset 3174514f5e3Sopenharmony_ci FreeObjectSet<T> *next = current->next_; 3184514f5e3Sopenharmony_ci cb(current); 3194514f5e3Sopenharmony_ci current = next; 3204514f5e3Sopenharmony_ci } 3214514f5e3Sopenharmony_ci} 3224514f5e3Sopenharmony_ci 3234514f5e3Sopenharmony_citemplate<typename T> 3244514f5e3Sopenharmony_citemplate<class Callback> 3254514f5e3Sopenharmony_civoid FreeObjectList<T>::EnumerateTopAndLastSets(const Callback &cb) const 3264514f5e3Sopenharmony_ci{ 3274514f5e3Sopenharmony_ci for (SetType i = 0; i < NUMBER_OF_SETS; i++) { 3284514f5e3Sopenharmony_ci cb(sets_[i], lastSets_[i]); 3294514f5e3Sopenharmony_ci } 3304514f5e3Sopenharmony_ci} 3314514f5e3Sopenharmony_ci} // namespace panda::ecmascript 332