/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecmascript/mem/free_object_set.h" #include "ecmascript/free_object.h" namespace panda::ecmascript { template void FreeObjectSet::Free(uintptr_t begin, size_t size) { auto freeObject = T::Cast(begin); ASSERT(freeObject->IsFreeObject()); freeObject->SetNext(freeObject_); freeObject_ = freeObject; available_ += size; } template void FreeObjectSet::Free(uintptr_t, size_t); template <> void FreeObjectSet::Free(uintptr_t begin, size_t size) { ASSERT(begin >= memDescPool_->JitFortBegin() && size <= memDescPool_->JitFortSize()); auto freeObject = memDescPool_->GetDescFromPool(); ASSERT(freeObject != nullptr); freeObject->SetMem(begin); freeObject->SetSize(size); freeObject->SetNext(freeObject_); freeObject_ = freeObject; available_ += size; } template void FreeObjectSet::Rebuild() { freeObject_ = T::Cast(INVALID_OBJPTR); available_ = 0; isAdded_ = 0; next_ = nullptr; prev_ = nullptr; } template void FreeObjectSet::Rebuild(); template <> void FreeObjectSet::Rebuild() { MemDesc *current = freeObject_; while (!MemDescPool::IsEmpty(current)) { // put desc back to free pool auto next = current->GetNext(); memDescPool_->ReturnDescToPool(current); current = next; } freeObject_ = MemDesc::Cast(INVALID_OBJPTR); available_ = 0; isAdded_ = 0; next_ = nullptr; prev_ = nullptr; } template T *FreeObjectSet::ObtainSmallFreeObject(size_t size) { T *curFreeObject = T::Cast(INVALID_OBJPTR); if (freeObject_ != T::Cast(INVALID_OBJPTR)) { freeObject_->AsanUnPoisonFreeObject(); if (freeObject_->Available() >= size) { curFreeObject = freeObject_; freeObject_ = freeObject_->GetNext(); curFreeObject->SetNext(T::Cast(INVALID_OBJPTR)); available_ -= curFreeObject->Available(); // It need to mark unpoison when object being allocated in freelist. ASAN_UNPOISON_MEMORY_REGION(curFreeObject, curFreeObject->Available()); } else { freeObject_->AsanPoisonFreeObject(); } } return curFreeObject; } template FreeObject *FreeObjectSet::ObtainSmallFreeObject(size_t); template MemDesc *FreeObjectSet::ObtainSmallFreeObject(size_t); template T *FreeObjectSet::ObtainLargeFreeObject(size_t size) { T *prevFreeObject = freeObject_; T *curFreeObject = freeObject_; while (curFreeObject != T::Cast(INVALID_OBJPTR)) { curFreeObject->AsanUnPoisonFreeObject(); if (curFreeObject->Available() >= size) { if (curFreeObject == freeObject_) { freeObject_ = curFreeObject->GetNext(); } else { prevFreeObject->SetNext(curFreeObject->GetNext()); prevFreeObject->AsanPoisonFreeObject(); } curFreeObject->SetNext(T::Cast(INVALID_OBJPTR)); available_ -= curFreeObject->Available(); ASAN_UNPOISON_MEMORY_REGION(curFreeObject, curFreeObject->Available()); return curFreeObject; } if (prevFreeObject != curFreeObject) { prevFreeObject->AsanPoisonFreeObject(); } prevFreeObject = curFreeObject; curFreeObject = curFreeObject->GetNext(); } return T::Cast(INVALID_OBJPTR); } template FreeObject *FreeObjectSet::ObtainLargeFreeObject(size_t); template MemDesc *FreeObjectSet::ObtainLargeFreeObject(size_t); template T *FreeObjectSet::LookupSmallFreeObject(size_t size) { if (freeObject_ != INVALID_OBJECT) { freeObject_->AsanUnPoisonFreeObject(); if (freeObject_->Available() >= size) { freeObject_->AsanPoisonFreeObject(); return freeObject_; } freeObject_->AsanPoisonFreeObject(); } return INVALID_OBJECT; } template FreeObject *FreeObjectSet::LookupSmallFreeObject(size_t); template T *FreeObjectSet::LookupLargeFreeObject(size_t size) { if (available_ < size) { return INVALID_OBJECT; } T *curFreeObject = freeObject_; while (curFreeObject != INVALID_OBJECT) { curFreeObject->AsanUnPoisonFreeObject(); if (curFreeObject->Available() >= size) { curFreeObject->AsanPoisonFreeObject(); return curFreeObject; } T *preFreeObject = curFreeObject; curFreeObject = curFreeObject->GetNext(); preFreeObject->AsanPoisonFreeObject(); } return INVALID_OBJECT; } template FreeObject *FreeObjectSet::LookupLargeFreeObject(size_t); } // namespace panda::ecmascript