• 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 #ifndef ECMASCRIPT_MEM_ALLOCATOR_INL_H
17 #define ECMASCRIPT_MEM_ALLOCATOR_INL_H
18 
19 #include <cstdlib>
20 
21 #include "ecmascript/free_object.h"
22 #include "ecmascript/mem/allocator.h"
23 #include "ecmascript/mem/heap.h"
24 
25 namespace panda::ecmascript {
BumpPointerAllocator(uintptr_t begin,uintptr_t end)26 BumpPointerAllocator::BumpPointerAllocator(uintptr_t begin, uintptr_t end) : begin_(begin), top_(begin), end_(end) {}
27 
Reset()28 void BumpPointerAllocator::Reset()
29 {
30     begin_ = 0;
31     top_ = 0;
32     end_ = 0;
33 }
34 
Reset(uintptr_t begin,uintptr_t end)35 void BumpPointerAllocator::Reset(uintptr_t begin, uintptr_t end)
36 {
37     begin_ = begin;
38     top_ = begin;
39     end_ = end;
40 }
41 
Allocate(size_t size)42 uintptr_t BumpPointerAllocator::Allocate(size_t size)
43 {
44     ASSERT(size != 0);
45     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
46     if (UNLIKELY(top_ + size > end_)) {
47         return 0;
48     }
49     uintptr_t result = top_;
50     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
51     top_ += size;
52     return result;
53 }
54 
FreeListAllocator(Heap * heap)55 FreeListAllocator::FreeListAllocator(Heap *heap) : heap_(heap)
56 {
57     freeList_ = std::make_unique<FreeObjectList>();
58 }
59 
Initialize(Region * region)60 void FreeListAllocator::Initialize(Region *region)
61 {
62     bpAllocator_.Reset(region->GetBegin(), region->GetEnd());
63 }
64 
Reset(Heap * heap)65 void FreeListAllocator::Reset(Heap *heap)
66 {
67     heap_ = heap;
68     freeList_ = std::make_unique<FreeObjectList>();
69     FreeBumpPoint();
70 }
71 
AddFree(Region * region)72 void FreeListAllocator::AddFree(Region *region)
73 {
74     auto begin = region->GetBegin();
75     auto end = region->GetEnd();
76     FreeBumpPoint();
77     bpAllocator_.Reset(begin, end);
78 }
79 
Allocate(size_t size)80 uintptr_t FreeListAllocator::Allocate(size_t size)
81 {
82     auto ret = bpAllocator_.Allocate(size);
83     if (LIKELY(ret != 0)) {
84         allocationSizeAccumulator_ += size;
85         Region::ObjectAddressToRange(ret)->IncrementAliveObject(size);
86         return ret;
87     }
88     FreeObject *object = freeList_->Allocate(size);
89     if (object != nullptr) {
90         ret = Allocate(object, size);
91     }
92     return ret;
93 }
94 
Allocate(FreeObject * object,size_t size)95 uintptr_t FreeListAllocator::Allocate(FreeObject *object, size_t size)
96 {
97     uintptr_t begin = object->GetBegin();
98     uintptr_t end = object->GetEnd();
99     uintptr_t remainSize = end - begin - size;
100     ASSERT(remainSize >= 0);
101     // Keep a longest freeObject between bump-pointer and free object that just allocated
102     allocationSizeAccumulator_ += size;
103     if (remainSize <= bpAllocator_.Available()) {
104         Free(begin + size, remainSize);
105         Region::ObjectAddressToRange(begin)->IncrementAliveObject(size);
106         return begin;
107     } else {
108         FreeBumpPoint();
109         bpAllocator_.Reset(begin, end);
110         auto ret = bpAllocator_.Allocate(size);
111         if (ret != 0) {
112             Region::ObjectAddressToRange(ret)->IncrementAliveObject(size);
113         }
114         return ret;
115     }
116 }
117 
FreeBumpPoint()118 void FreeListAllocator::FreeBumpPoint()
119 {
120     auto begin = bpAllocator_.GetTop();
121     auto size = bpAllocator_.Available();
122     bpAllocator_.Reset();
123     Free(begin, size);
124 }
125 
FillBumpPoint()126 void FreeListAllocator::FillBumpPoint()
127 {
128     size_t size = bpAllocator_.Available();
129     if (size != 0) {
130         FreeObject::FillFreeObject(heap_->GetEcmaVM(), bpAllocator_.GetTop(), size);
131     }
132 }
133 
Free(uintptr_t begin,size_t size,bool isAdd)134 void FreeListAllocator::Free(uintptr_t begin, size_t size, bool isAdd)
135 {
136     ASSERT(heap_ != nullptr);
137     ASSERT(size >= 0);
138     if (size != 0) {
139         FreeObject::FillFreeObject(heap_->GetEcmaVM(), begin, size);
140         freeList_->Free(begin, size, isAdd);
141     }
142 }
143 
LookupSuitableFreeObject(size_t size)144 uintptr_t FreeListAllocator::LookupSuitableFreeObject(size_t size)
145 {
146     auto freeObject = freeList_->LookupSuitableFreeObject(size);
147     if (freeObject != nullptr) {
148         return freeObject->GetBegin();
149     }
150     return 0;
151 }
152 
RebuildFreeList()153 void FreeListAllocator::RebuildFreeList()
154 {
155     bpAllocator_.Reset();
156     freeList_->Rebuild();
157 }
158 
CollectFreeObjectSet(Region * region)159 inline void FreeListAllocator::CollectFreeObjectSet(Region *region)
160 {
161     region->EnumerateSets([&](FreeObjectSet *set) {
162         if (set == nullptr || set->Empty()) {
163             return;
164         }
165         freeList_->AddSet(set);
166     });
167     freeList_->IncrementWastedSize(region->GetWastedSize());
168 }
169 
DetachFreeObjectSet(Region * region)170 inline void FreeListAllocator::DetachFreeObjectSet(Region *region)
171 {
172     region->EnumerateSets([&](FreeObjectSet *set) {
173         if (set == nullptr || set->Empty()) {
174             return;
175         }
176         freeList_->RemoveSet(set);
177     });
178     freeList_->DecrementWastedSize(region->GetWastedSize());
179 }
180 
GetAvailableSize()181 size_t FreeListAllocator::GetAvailableSize() const
182 {
183     return freeList_->GetFreeObjectSize() + bpAllocator_.Available();
184 }
185 
GetWastedSize()186 size_t FreeListAllocator::GetWastedSize() const
187 {
188     return freeList_->GetWastedSize();
189 }
190 }  // namespace panda::ecmascript
191 #endif  // ECMASCRIPT_MEM_ALLOCATOR_INL_H
192