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/mem/free_object_set.h" 17 18#include "ecmascript/free_object.h" 19 20namespace panda::ecmascript { 21template <typename T> 22void FreeObjectSet<T>::Free(uintptr_t begin, size_t size) 23{ 24 auto freeObject = T::Cast(begin); 25 ASSERT(freeObject->IsFreeObject()); 26 freeObject->SetNext(freeObject_); 27 freeObject_ = freeObject; 28 available_ += size; 29} 30 31template void FreeObjectSet<FreeObject>::Free(uintptr_t, size_t); 32template <> 33void FreeObjectSet<MemDesc>::Free(uintptr_t begin, size_t size) 34{ 35 ASSERT(begin >= memDescPool_->JitFortBegin() && 36 size <= memDescPool_->JitFortSize()); 37 38 auto freeObject = memDescPool_->GetDescFromPool(); 39 ASSERT(freeObject != nullptr); 40 freeObject->SetMem(begin); 41 freeObject->SetSize(size); 42 freeObject->SetNext(freeObject_); 43 freeObject_ = freeObject; 44 available_ += size; 45} 46 47template <typename T> 48void FreeObjectSet<T>::Rebuild() 49{ 50 freeObject_ = T::Cast(INVALID_OBJPTR); 51 available_ = 0; 52 isAdded_ = 0; 53 next_ = nullptr; 54 prev_ = nullptr; 55} 56 57template void FreeObjectSet<FreeObject>::Rebuild(); 58template <> 59void FreeObjectSet<MemDesc>::Rebuild() 60{ 61 MemDesc *current = freeObject_; 62 while (!MemDescPool::IsEmpty(current)) { 63 // put desc back to free pool 64 auto next = current->GetNext(); 65 memDescPool_->ReturnDescToPool(current); 66 current = next; 67 } 68 freeObject_ = MemDesc::Cast(INVALID_OBJPTR); 69 available_ = 0; 70 isAdded_ = 0; 71 next_ = nullptr; 72 prev_ = nullptr; 73} 74 75template <typename T> 76T *FreeObjectSet<T>::ObtainSmallFreeObject(size_t size) 77{ 78 T *curFreeObject = T::Cast(INVALID_OBJPTR); 79 if (freeObject_ != T::Cast(INVALID_OBJPTR)) { 80 freeObject_->AsanUnPoisonFreeObject(); 81 if (freeObject_->Available() >= size) { 82 curFreeObject = freeObject_; 83 freeObject_ = freeObject_->GetNext(); 84 curFreeObject->SetNext(T::Cast(INVALID_OBJPTR)); 85 available_ -= curFreeObject->Available(); 86 // It need to mark unpoison when object being allocated in freelist. 87 ASAN_UNPOISON_MEMORY_REGION(curFreeObject, curFreeObject->Available()); 88 } else { 89 freeObject_->AsanPoisonFreeObject(); 90 } 91 } 92 return curFreeObject; 93} 94 95template FreeObject *FreeObjectSet<FreeObject>::ObtainSmallFreeObject(size_t); 96template MemDesc *FreeObjectSet<MemDesc>::ObtainSmallFreeObject(size_t); 97 98template <typename T> 99T *FreeObjectSet<T>::ObtainLargeFreeObject(size_t size) 100{ 101 T *prevFreeObject = freeObject_; 102 T *curFreeObject = freeObject_; 103 while (curFreeObject != T::Cast(INVALID_OBJPTR)) { 104 curFreeObject->AsanUnPoisonFreeObject(); 105 if (curFreeObject->Available() >= size) { 106 if (curFreeObject == freeObject_) { 107 freeObject_ = curFreeObject->GetNext(); 108 } else { 109 prevFreeObject->SetNext(curFreeObject->GetNext()); 110 prevFreeObject->AsanPoisonFreeObject(); 111 } 112 curFreeObject->SetNext(T::Cast(INVALID_OBJPTR)); 113 available_ -= curFreeObject->Available(); 114 ASAN_UNPOISON_MEMORY_REGION(curFreeObject, curFreeObject->Available()); 115 return curFreeObject; 116 } 117 if (prevFreeObject != curFreeObject) { 118 prevFreeObject->AsanPoisonFreeObject(); 119 } 120 prevFreeObject = curFreeObject; 121 curFreeObject = curFreeObject->GetNext(); 122 } 123 return T::Cast(INVALID_OBJPTR); 124} 125 126template FreeObject *FreeObjectSet<FreeObject>::ObtainLargeFreeObject(size_t); 127template MemDesc *FreeObjectSet<MemDesc>::ObtainLargeFreeObject(size_t); 128 129template <typename T> 130T *FreeObjectSet<T>::LookupSmallFreeObject(size_t size) 131{ 132 if (freeObject_ != INVALID_OBJECT) { 133 freeObject_->AsanUnPoisonFreeObject(); 134 if (freeObject_->Available() >= size) { 135 freeObject_->AsanPoisonFreeObject(); 136 return freeObject_; 137 } 138 freeObject_->AsanPoisonFreeObject(); 139 } 140 return INVALID_OBJECT; 141} 142 143template FreeObject *FreeObjectSet<FreeObject>::LookupSmallFreeObject(size_t); 144 145template <typename T> 146T *FreeObjectSet<T>::LookupLargeFreeObject(size_t size) 147{ 148 if (available_ < size) { 149 return INVALID_OBJECT; 150 } 151 T *curFreeObject = freeObject_; 152 while (curFreeObject != INVALID_OBJECT) { 153 curFreeObject->AsanUnPoisonFreeObject(); 154 if (curFreeObject->Available() >= size) { 155 curFreeObject->AsanPoisonFreeObject(); 156 return curFreeObject; 157 } 158 T *preFreeObject = curFreeObject; 159 curFreeObject = curFreeObject->GetNext(); 160 preFreeObject->AsanPoisonFreeObject(); 161 } 162 return INVALID_OBJECT; 163} 164 165template FreeObject *FreeObjectSet<FreeObject>::LookupLargeFreeObject(size_t); 166 167} // namespace panda::ecmascript 168