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 }
30
31 template void FreeObjectSet<FreeObject>::Free(uintptr_t, size_t);
32 template <>
Free(uintptr_t begin, size_t size)33 void 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
47 template <typename T>
Rebuild()48 void FreeObjectSet<T>::Rebuild()
49 {
50 freeObject_ = T::Cast(INVALID_OBJPTR);
51 available_ = 0;
52 isAdded_ = 0;
53 next_ = nullptr;
54 prev_ = nullptr;
55 }
56
57 template void FreeObjectSet<FreeObject>::Rebuild();
58 template <>
Rebuild()59 void 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
75 template <typename T>
ObtainSmallFreeObject(size_t size)76 T *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
95 template FreeObject *FreeObjectSet<FreeObject>::ObtainSmallFreeObject(size_t);
96 template MemDesc *FreeObjectSet<MemDesc>::ObtainSmallFreeObject(size_t);
97
98 template <typename T>
ObtainLargeFreeObject(size_t size)99 T *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
126 template FreeObject *FreeObjectSet<FreeObject>::ObtainLargeFreeObject(size_t);
127 template MemDesc *FreeObjectSet<MemDesc>::ObtainLargeFreeObject(size_t);
128
129 template <typename T>
LookupSmallFreeObject(size_t size)130 T *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
143 template FreeObject *FreeObjectSet<FreeObject>::LookupSmallFreeObject(size_t);
144
145 template <typename T>
LookupLargeFreeObject(size_t size)146 T *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
165 template FreeObject *FreeObjectSet<FreeObject>::LookupLargeFreeObject(size_t);
166
167 } // namespace panda::ecmascript
168