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