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/mem/free_object_set.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/free_object.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_cinamespace panda::ecmascript {
214514f5e3Sopenharmony_citemplate <typename T>
224514f5e3Sopenharmony_civoid FreeObjectSet<T>::Free(uintptr_t begin, size_t size)
234514f5e3Sopenharmony_ci{
244514f5e3Sopenharmony_ci    auto freeObject = T::Cast(begin);
254514f5e3Sopenharmony_ci    ASSERT(freeObject->IsFreeObject());
264514f5e3Sopenharmony_ci    freeObject->SetNext(freeObject_);
274514f5e3Sopenharmony_ci    freeObject_ = freeObject;
284514f5e3Sopenharmony_ci    available_ += size;
294514f5e3Sopenharmony_ci}
304514f5e3Sopenharmony_ci
314514f5e3Sopenharmony_citemplate void FreeObjectSet<FreeObject>::Free(uintptr_t, size_t);
324514f5e3Sopenharmony_citemplate <>
334514f5e3Sopenharmony_civoid FreeObjectSet<MemDesc>::Free(uintptr_t begin, size_t size)
344514f5e3Sopenharmony_ci{
354514f5e3Sopenharmony_ci    ASSERT(begin >= memDescPool_->JitFortBegin() &&
364514f5e3Sopenharmony_ci        size <= memDescPool_->JitFortSize());
374514f5e3Sopenharmony_ci
384514f5e3Sopenharmony_ci    auto freeObject = memDescPool_->GetDescFromPool();
394514f5e3Sopenharmony_ci    ASSERT(freeObject != nullptr);
404514f5e3Sopenharmony_ci    freeObject->SetMem(begin);
414514f5e3Sopenharmony_ci    freeObject->SetSize(size);
424514f5e3Sopenharmony_ci    freeObject->SetNext(freeObject_);
434514f5e3Sopenharmony_ci    freeObject_ = freeObject;
444514f5e3Sopenharmony_ci    available_ += size;
454514f5e3Sopenharmony_ci}
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_citemplate <typename T>
484514f5e3Sopenharmony_civoid FreeObjectSet<T>::Rebuild()
494514f5e3Sopenharmony_ci{
504514f5e3Sopenharmony_ci    freeObject_ = T::Cast(INVALID_OBJPTR);
514514f5e3Sopenharmony_ci    available_ = 0;
524514f5e3Sopenharmony_ci    isAdded_ = 0;
534514f5e3Sopenharmony_ci    next_ = nullptr;
544514f5e3Sopenharmony_ci    prev_ = nullptr;
554514f5e3Sopenharmony_ci}
564514f5e3Sopenharmony_ci
574514f5e3Sopenharmony_citemplate void FreeObjectSet<FreeObject>::Rebuild();
584514f5e3Sopenharmony_citemplate <>
594514f5e3Sopenharmony_civoid FreeObjectSet<MemDesc>::Rebuild()
604514f5e3Sopenharmony_ci{
614514f5e3Sopenharmony_ci    MemDesc *current = freeObject_;
624514f5e3Sopenharmony_ci    while (!MemDescPool::IsEmpty(current)) {
634514f5e3Sopenharmony_ci        // put desc back to free pool
644514f5e3Sopenharmony_ci        auto next = current->GetNext();
654514f5e3Sopenharmony_ci        memDescPool_->ReturnDescToPool(current);
664514f5e3Sopenharmony_ci        current = next;
674514f5e3Sopenharmony_ci    }
684514f5e3Sopenharmony_ci    freeObject_ = MemDesc::Cast(INVALID_OBJPTR);
694514f5e3Sopenharmony_ci    available_ = 0;
704514f5e3Sopenharmony_ci    isAdded_ = 0;
714514f5e3Sopenharmony_ci    next_ = nullptr;
724514f5e3Sopenharmony_ci    prev_ = nullptr;
734514f5e3Sopenharmony_ci}
744514f5e3Sopenharmony_ci
754514f5e3Sopenharmony_citemplate <typename T>
764514f5e3Sopenharmony_ciT *FreeObjectSet<T>::ObtainSmallFreeObject(size_t size)
774514f5e3Sopenharmony_ci{
784514f5e3Sopenharmony_ci    T *curFreeObject = T::Cast(INVALID_OBJPTR);
794514f5e3Sopenharmony_ci    if (freeObject_ != T::Cast(INVALID_OBJPTR)) {
804514f5e3Sopenharmony_ci        freeObject_->AsanUnPoisonFreeObject();
814514f5e3Sopenharmony_ci        if (freeObject_->Available() >= size) {
824514f5e3Sopenharmony_ci            curFreeObject = freeObject_;
834514f5e3Sopenharmony_ci            freeObject_ = freeObject_->GetNext();
844514f5e3Sopenharmony_ci            curFreeObject->SetNext(T::Cast(INVALID_OBJPTR));
854514f5e3Sopenharmony_ci            available_ -= curFreeObject->Available();
864514f5e3Sopenharmony_ci            // It need to mark unpoison when object being allocated in freelist.
874514f5e3Sopenharmony_ci            ASAN_UNPOISON_MEMORY_REGION(curFreeObject, curFreeObject->Available());
884514f5e3Sopenharmony_ci        } else {
894514f5e3Sopenharmony_ci            freeObject_->AsanPoisonFreeObject();
904514f5e3Sopenharmony_ci        }
914514f5e3Sopenharmony_ci    }
924514f5e3Sopenharmony_ci    return curFreeObject;
934514f5e3Sopenharmony_ci}
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_citemplate FreeObject *FreeObjectSet<FreeObject>::ObtainSmallFreeObject(size_t);
964514f5e3Sopenharmony_citemplate MemDesc *FreeObjectSet<MemDesc>::ObtainSmallFreeObject(size_t);
974514f5e3Sopenharmony_ci
984514f5e3Sopenharmony_citemplate <typename T>
994514f5e3Sopenharmony_ciT *FreeObjectSet<T>::ObtainLargeFreeObject(size_t size)
1004514f5e3Sopenharmony_ci{
1014514f5e3Sopenharmony_ci    T *prevFreeObject = freeObject_;
1024514f5e3Sopenharmony_ci    T *curFreeObject = freeObject_;
1034514f5e3Sopenharmony_ci    while (curFreeObject != T::Cast(INVALID_OBJPTR)) {
1044514f5e3Sopenharmony_ci        curFreeObject->AsanUnPoisonFreeObject();
1054514f5e3Sopenharmony_ci        if (curFreeObject->Available() >= size) {
1064514f5e3Sopenharmony_ci            if (curFreeObject == freeObject_) {
1074514f5e3Sopenharmony_ci                freeObject_ = curFreeObject->GetNext();
1084514f5e3Sopenharmony_ci            } else {
1094514f5e3Sopenharmony_ci                prevFreeObject->SetNext(curFreeObject->GetNext());
1104514f5e3Sopenharmony_ci                prevFreeObject->AsanPoisonFreeObject();
1114514f5e3Sopenharmony_ci            }
1124514f5e3Sopenharmony_ci            curFreeObject->SetNext(T::Cast(INVALID_OBJPTR));
1134514f5e3Sopenharmony_ci            available_ -= curFreeObject->Available();
1144514f5e3Sopenharmony_ci            ASAN_UNPOISON_MEMORY_REGION(curFreeObject, curFreeObject->Available());
1154514f5e3Sopenharmony_ci            return curFreeObject;
1164514f5e3Sopenharmony_ci        }
1174514f5e3Sopenharmony_ci        if (prevFreeObject != curFreeObject) {
1184514f5e3Sopenharmony_ci            prevFreeObject->AsanPoisonFreeObject();
1194514f5e3Sopenharmony_ci        }
1204514f5e3Sopenharmony_ci        prevFreeObject = curFreeObject;
1214514f5e3Sopenharmony_ci        curFreeObject = curFreeObject->GetNext();
1224514f5e3Sopenharmony_ci    }
1234514f5e3Sopenharmony_ci    return T::Cast(INVALID_OBJPTR);
1244514f5e3Sopenharmony_ci}
1254514f5e3Sopenharmony_ci
1264514f5e3Sopenharmony_citemplate FreeObject *FreeObjectSet<FreeObject>::ObtainLargeFreeObject(size_t);
1274514f5e3Sopenharmony_citemplate MemDesc *FreeObjectSet<MemDesc>::ObtainLargeFreeObject(size_t);
1284514f5e3Sopenharmony_ci
1294514f5e3Sopenharmony_citemplate <typename T>
1304514f5e3Sopenharmony_ciT *FreeObjectSet<T>::LookupSmallFreeObject(size_t size)
1314514f5e3Sopenharmony_ci{
1324514f5e3Sopenharmony_ci    if (freeObject_ != INVALID_OBJECT) {
1334514f5e3Sopenharmony_ci        freeObject_->AsanUnPoisonFreeObject();
1344514f5e3Sopenharmony_ci        if (freeObject_->Available() >= size) {
1354514f5e3Sopenharmony_ci            freeObject_->AsanPoisonFreeObject();
1364514f5e3Sopenharmony_ci            return freeObject_;
1374514f5e3Sopenharmony_ci        }
1384514f5e3Sopenharmony_ci        freeObject_->AsanPoisonFreeObject();
1394514f5e3Sopenharmony_ci    }
1404514f5e3Sopenharmony_ci    return INVALID_OBJECT;
1414514f5e3Sopenharmony_ci}
1424514f5e3Sopenharmony_ci
1434514f5e3Sopenharmony_citemplate FreeObject *FreeObjectSet<FreeObject>::LookupSmallFreeObject(size_t);
1444514f5e3Sopenharmony_ci
1454514f5e3Sopenharmony_citemplate <typename T>
1464514f5e3Sopenharmony_ciT *FreeObjectSet<T>::LookupLargeFreeObject(size_t size)
1474514f5e3Sopenharmony_ci{
1484514f5e3Sopenharmony_ci    if (available_ < size) {
1494514f5e3Sopenharmony_ci        return INVALID_OBJECT;
1504514f5e3Sopenharmony_ci    }
1514514f5e3Sopenharmony_ci    T *curFreeObject = freeObject_;
1524514f5e3Sopenharmony_ci    while (curFreeObject != INVALID_OBJECT) {
1534514f5e3Sopenharmony_ci        curFreeObject->AsanUnPoisonFreeObject();
1544514f5e3Sopenharmony_ci        if (curFreeObject->Available() >= size) {
1554514f5e3Sopenharmony_ci            curFreeObject->AsanPoisonFreeObject();
1564514f5e3Sopenharmony_ci            return curFreeObject;
1574514f5e3Sopenharmony_ci        }
1584514f5e3Sopenharmony_ci        T *preFreeObject = curFreeObject;
1594514f5e3Sopenharmony_ci        curFreeObject = curFreeObject->GetNext();
1604514f5e3Sopenharmony_ci        preFreeObject->AsanPoisonFreeObject();
1614514f5e3Sopenharmony_ci    }
1624514f5e3Sopenharmony_ci    return INVALID_OBJECT;
1634514f5e3Sopenharmony_ci}
1644514f5e3Sopenharmony_ci
1654514f5e3Sopenharmony_citemplate FreeObject *FreeObjectSet<FreeObject>::LookupLargeFreeObject(size_t);
1664514f5e3Sopenharmony_ci
1674514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
168