xref: /aosp_15_r20/art/runtime/gc/allocator/rosalloc.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_GC_ALLOCATOR_ROSALLOC_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_GC_ALLOCATOR_ROSALLOC_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
21*795d594fSAndroid Build Coastguard Worker #include <stdlib.h>
22*795d594fSAndroid Build Coastguard Worker #include <sys/mman.h>
23*795d594fSAndroid Build Coastguard Worker #include <memory>
24*795d594fSAndroid Build Coastguard Worker #include <set>
25*795d594fSAndroid Build Coastguard Worker #include <string>
26*795d594fSAndroid Build Coastguard Worker #include <unordered_set>
27*795d594fSAndroid Build Coastguard Worker #include <vector>
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker #include "base/allocator.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
36*795d594fSAndroid Build Coastguard Worker #include "runtime_globals.h"
37*795d594fSAndroid Build Coastguard Worker #include "thread.h"
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker namespace gc {
42*795d594fSAndroid Build Coastguard Worker namespace allocator {
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker // A runs-of-slots memory allocator.
45*795d594fSAndroid Build Coastguard Worker class RosAlloc {
46*795d594fSAndroid Build Coastguard Worker  private:
47*795d594fSAndroid Build Coastguard Worker   // Represents a run of free pages.
48*795d594fSAndroid Build Coastguard Worker   class FreePageRun {
49*795d594fSAndroid Build Coastguard Worker    public:
50*795d594fSAndroid Build Coastguard Worker     uint8_t magic_num_;  // The magic number used for debugging only.
51*795d594fSAndroid Build Coastguard Worker 
IsFree()52*795d594fSAndroid Build Coastguard Worker     bool IsFree() const {
53*795d594fSAndroid Build Coastguard Worker       return !kIsDebugBuild || magic_num_ == kMagicNumFree;
54*795d594fSAndroid Build Coastguard Worker     }
ByteSize(RosAlloc * rosalloc)55*795d594fSAndroid Build Coastguard Worker     size_t ByteSize(RosAlloc* rosalloc) const REQUIRES(rosalloc->lock_) {
56*795d594fSAndroid Build Coastguard Worker       const uint8_t* fpr_base = reinterpret_cast<const uint8_t*>(this);
57*795d594fSAndroid Build Coastguard Worker       size_t pm_idx = rosalloc->ToPageMapIndex(fpr_base);
58*795d594fSAndroid Build Coastguard Worker       size_t byte_size = rosalloc->free_page_run_size_map_[pm_idx];
59*795d594fSAndroid Build Coastguard Worker       DCHECK_GE(byte_size, static_cast<size_t>(0));
60*795d594fSAndroid Build Coastguard Worker       DCHECK_ALIGNED_PARAM(byte_size, gPageSize);
61*795d594fSAndroid Build Coastguard Worker       return byte_size;
62*795d594fSAndroid Build Coastguard Worker     }
SetByteSize(RosAlloc * rosalloc,size_t byte_size)63*795d594fSAndroid Build Coastguard Worker     void SetByteSize(RosAlloc* rosalloc, size_t byte_size)
64*795d594fSAndroid Build Coastguard Worker         REQUIRES(rosalloc->lock_) {
65*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(ModuloPageSize(byte_size), static_cast<size_t>(0));
66*795d594fSAndroid Build Coastguard Worker       uint8_t* fpr_base = reinterpret_cast<uint8_t*>(this);
67*795d594fSAndroid Build Coastguard Worker       size_t pm_idx = rosalloc->ToPageMapIndex(fpr_base);
68*795d594fSAndroid Build Coastguard Worker       rosalloc->free_page_run_size_map_[pm_idx] = byte_size;
69*795d594fSAndroid Build Coastguard Worker     }
Begin()70*795d594fSAndroid Build Coastguard Worker     void* Begin() {
71*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<void*>(this);
72*795d594fSAndroid Build Coastguard Worker     }
End(RosAlloc * rosalloc)73*795d594fSAndroid Build Coastguard Worker     void* End(RosAlloc* rosalloc) REQUIRES(rosalloc->lock_) {
74*795d594fSAndroid Build Coastguard Worker       uint8_t* fpr_base = reinterpret_cast<uint8_t*>(this);
75*795d594fSAndroid Build Coastguard Worker       uint8_t* end = fpr_base + ByteSize(rosalloc);
76*795d594fSAndroid Build Coastguard Worker       return end;
77*795d594fSAndroid Build Coastguard Worker     }
IsLargerThanPageReleaseThreshold(RosAlloc * rosalloc)78*795d594fSAndroid Build Coastguard Worker     bool IsLargerThanPageReleaseThreshold(RosAlloc* rosalloc)
79*795d594fSAndroid Build Coastguard Worker         REQUIRES(rosalloc->lock_) {
80*795d594fSAndroid Build Coastguard Worker       return ByteSize(rosalloc) >= rosalloc->page_release_size_threshold_;
81*795d594fSAndroid Build Coastguard Worker     }
IsAtEndOfSpace(RosAlloc * rosalloc)82*795d594fSAndroid Build Coastguard Worker     bool IsAtEndOfSpace(RosAlloc* rosalloc)
83*795d594fSAndroid Build Coastguard Worker         REQUIRES(rosalloc->lock_) {
84*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<uint8_t*>(this) + ByteSize(rosalloc) == rosalloc->base_ + rosalloc->footprint_;
85*795d594fSAndroid Build Coastguard Worker     }
ShouldReleasePages(RosAlloc * rosalloc)86*795d594fSAndroid Build Coastguard Worker     bool ShouldReleasePages(RosAlloc* rosalloc) REQUIRES(rosalloc->lock_) {
87*795d594fSAndroid Build Coastguard Worker       switch (rosalloc->page_release_mode_) {
88*795d594fSAndroid Build Coastguard Worker         case kPageReleaseModeNone:
89*795d594fSAndroid Build Coastguard Worker           return false;
90*795d594fSAndroid Build Coastguard Worker         case kPageReleaseModeEnd:
91*795d594fSAndroid Build Coastguard Worker           return IsAtEndOfSpace(rosalloc);
92*795d594fSAndroid Build Coastguard Worker         case kPageReleaseModeSize:
93*795d594fSAndroid Build Coastguard Worker           return IsLargerThanPageReleaseThreshold(rosalloc);
94*795d594fSAndroid Build Coastguard Worker         case kPageReleaseModeSizeAndEnd:
95*795d594fSAndroid Build Coastguard Worker           return IsLargerThanPageReleaseThreshold(rosalloc) && IsAtEndOfSpace(rosalloc);
96*795d594fSAndroid Build Coastguard Worker         case kPageReleaseModeAll:
97*795d594fSAndroid Build Coastguard Worker           return true;
98*795d594fSAndroid Build Coastguard Worker       }
99*795d594fSAndroid Build Coastguard Worker     }
ReleasePages(RosAlloc * rosalloc)100*795d594fSAndroid Build Coastguard Worker     void ReleasePages(RosAlloc* rosalloc) REQUIRES(rosalloc->lock_) {
101*795d594fSAndroid Build Coastguard Worker       uint8_t* start = reinterpret_cast<uint8_t*>(this);
102*795d594fSAndroid Build Coastguard Worker       size_t byte_size = ByteSize(rosalloc);
103*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(ModuloPageSize(byte_size), static_cast<size_t>(0));
104*795d594fSAndroid Build Coastguard Worker       if (ShouldReleasePages(rosalloc)) {
105*795d594fSAndroid Build Coastguard Worker         rosalloc->ReleasePageRange(start, start + byte_size);
106*795d594fSAndroid Build Coastguard Worker       }
107*795d594fSAndroid Build Coastguard Worker     }
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker    private:
110*795d594fSAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(FreePageRun);
111*795d594fSAndroid Build Coastguard Worker   };
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker   // The slot header.
114*795d594fSAndroid Build Coastguard Worker   class Slot {
115*795d594fSAndroid Build Coastguard Worker    public:
Next()116*795d594fSAndroid Build Coastguard Worker     Slot* Next() const {
117*795d594fSAndroid Build Coastguard Worker       return next_;
118*795d594fSAndroid Build Coastguard Worker     }
SetNext(Slot * next)119*795d594fSAndroid Build Coastguard Worker     void SetNext(Slot* next) {
120*795d594fSAndroid Build Coastguard Worker       next_ = next;
121*795d594fSAndroid Build Coastguard Worker     }
122*795d594fSAndroid Build Coastguard Worker     // The slot right before this slot in terms of the address.
Left(size_t bracket_size)123*795d594fSAndroid Build Coastguard Worker     Slot* Left(size_t bracket_size) {
124*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<Slot*>(reinterpret_cast<uintptr_t>(this) - bracket_size);
125*795d594fSAndroid Build Coastguard Worker     }
Clear()126*795d594fSAndroid Build Coastguard Worker     void Clear() {
127*795d594fSAndroid Build Coastguard Worker       next_ = nullptr;
128*795d594fSAndroid Build Coastguard Worker     }
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker    private:
131*795d594fSAndroid Build Coastguard Worker     Slot* next_;  // Next slot in the list.
132*795d594fSAndroid Build Coastguard Worker     friend class RosAlloc;
133*795d594fSAndroid Build Coastguard Worker   };
134*795d594fSAndroid Build Coastguard Worker 
135*795d594fSAndroid Build Coastguard Worker   // We use the tail (kUseTail == true) for the bulk or thread-local free lists to avoid the need to
136*795d594fSAndroid Build Coastguard Worker   // traverse the list from the head to the tail when merging free lists.
137*795d594fSAndroid Build Coastguard Worker   // We don't use the tail (kUseTail == false) for the free list to avoid the need to manage the
138*795d594fSAndroid Build Coastguard Worker   // tail in the allocation fast path for a performance reason.
139*795d594fSAndroid Build Coastguard Worker   template<bool kUseTail = true>
140*795d594fSAndroid Build Coastguard Worker   class SlotFreeList {
141*795d594fSAndroid Build Coastguard Worker    public:
SlotFreeList()142*795d594fSAndroid Build Coastguard Worker     SlotFreeList() : head_(0U), tail_(0), size_(0), padding_(0) {}
Head()143*795d594fSAndroid Build Coastguard Worker     Slot* Head() const {
144*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<Slot*>(head_);
145*795d594fSAndroid Build Coastguard Worker     }
Tail()146*795d594fSAndroid Build Coastguard Worker     Slot* Tail() const {
147*795d594fSAndroid Build Coastguard Worker       CHECK(kUseTail);
148*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<Slot*>(tail_);
149*795d594fSAndroid Build Coastguard Worker     }
Size()150*795d594fSAndroid Build Coastguard Worker     size_t Size() const {
151*795d594fSAndroid Build Coastguard Worker       return size_;
152*795d594fSAndroid Build Coastguard Worker     }
153*795d594fSAndroid Build Coastguard Worker     // Removes from the head of the free list.
Remove()154*795d594fSAndroid Build Coastguard Worker     Slot* Remove() {
155*795d594fSAndroid Build Coastguard Worker       Slot* slot;
156*795d594fSAndroid Build Coastguard Worker       if (kIsDebugBuild) {
157*795d594fSAndroid Build Coastguard Worker         Verify();
158*795d594fSAndroid Build Coastguard Worker       }
159*795d594fSAndroid Build Coastguard Worker       Slot** headp = reinterpret_cast<Slot**>(&head_);
160*795d594fSAndroid Build Coastguard Worker       Slot** tailp = kUseTail ? reinterpret_cast<Slot**>(&tail_) : nullptr;
161*795d594fSAndroid Build Coastguard Worker       Slot* old_head = *headp;
162*795d594fSAndroid Build Coastguard Worker       if (old_head == nullptr) {
163*795d594fSAndroid Build Coastguard Worker         // List was empty.
164*795d594fSAndroid Build Coastguard Worker         if (kUseTail) {
165*795d594fSAndroid Build Coastguard Worker           DCHECK(*tailp == nullptr);
166*795d594fSAndroid Build Coastguard Worker         }
167*795d594fSAndroid Build Coastguard Worker         return nullptr;
168*795d594fSAndroid Build Coastguard Worker       } else {
169*795d594fSAndroid Build Coastguard Worker         // List wasn't empty.
170*795d594fSAndroid Build Coastguard Worker         if (kUseTail) {
171*795d594fSAndroid Build Coastguard Worker           DCHECK(*tailp != nullptr);
172*795d594fSAndroid Build Coastguard Worker         }
173*795d594fSAndroid Build Coastguard Worker         Slot* old_head_next = old_head->Next();
174*795d594fSAndroid Build Coastguard Worker         slot = old_head;
175*795d594fSAndroid Build Coastguard Worker         *headp = old_head_next;
176*795d594fSAndroid Build Coastguard Worker         if (kUseTail && old_head_next == nullptr) {
177*795d594fSAndroid Build Coastguard Worker           // List becomes empty.
178*795d594fSAndroid Build Coastguard Worker           *tailp = nullptr;
179*795d594fSAndroid Build Coastguard Worker         }
180*795d594fSAndroid Build Coastguard Worker       }
181*795d594fSAndroid Build Coastguard Worker       slot->Clear();
182*795d594fSAndroid Build Coastguard Worker       --size_;
183*795d594fSAndroid Build Coastguard Worker       if (kIsDebugBuild) {
184*795d594fSAndroid Build Coastguard Worker         Verify();
185*795d594fSAndroid Build Coastguard Worker       }
186*795d594fSAndroid Build Coastguard Worker       return slot;
187*795d594fSAndroid Build Coastguard Worker     }
Add(Slot * slot)188*795d594fSAndroid Build Coastguard Worker     void Add(Slot* slot) {
189*795d594fSAndroid Build Coastguard Worker       if (kIsDebugBuild) {
190*795d594fSAndroid Build Coastguard Worker         Verify();
191*795d594fSAndroid Build Coastguard Worker       }
192*795d594fSAndroid Build Coastguard Worker       DCHECK(slot != nullptr);
193*795d594fSAndroid Build Coastguard Worker       DCHECK(slot->Next() == nullptr);
194*795d594fSAndroid Build Coastguard Worker       Slot** headp = reinterpret_cast<Slot**>(&head_);
195*795d594fSAndroid Build Coastguard Worker       Slot** tailp = kUseTail ? reinterpret_cast<Slot**>(&tail_) : nullptr;
196*795d594fSAndroid Build Coastguard Worker       Slot* old_head = *headp;
197*795d594fSAndroid Build Coastguard Worker       if (old_head == nullptr) {
198*795d594fSAndroid Build Coastguard Worker         // List was empty.
199*795d594fSAndroid Build Coastguard Worker         if (kUseTail) {
200*795d594fSAndroid Build Coastguard Worker           DCHECK(*tailp == nullptr);
201*795d594fSAndroid Build Coastguard Worker         }
202*795d594fSAndroid Build Coastguard Worker         *headp = slot;
203*795d594fSAndroid Build Coastguard Worker         if (kUseTail) {
204*795d594fSAndroid Build Coastguard Worker           *tailp = slot;
205*795d594fSAndroid Build Coastguard Worker         }
206*795d594fSAndroid Build Coastguard Worker       } else {
207*795d594fSAndroid Build Coastguard Worker         // List wasn't empty.
208*795d594fSAndroid Build Coastguard Worker         if (kUseTail) {
209*795d594fSAndroid Build Coastguard Worker           DCHECK(*tailp != nullptr);
210*795d594fSAndroid Build Coastguard Worker         }
211*795d594fSAndroid Build Coastguard Worker         *headp = slot;
212*795d594fSAndroid Build Coastguard Worker         slot->SetNext(old_head);
213*795d594fSAndroid Build Coastguard Worker       }
214*795d594fSAndroid Build Coastguard Worker       ++size_;
215*795d594fSAndroid Build Coastguard Worker       if (kIsDebugBuild) {
216*795d594fSAndroid Build Coastguard Worker         Verify();
217*795d594fSAndroid Build Coastguard Worker       }
218*795d594fSAndroid Build Coastguard Worker     }
219*795d594fSAndroid Build Coastguard Worker     // Merge the given list into this list. Empty the given list.
220*795d594fSAndroid Build Coastguard Worker     // Deliberately support only a kUseTail == true SlotFreeList parameter because 1) we don't
221*795d594fSAndroid Build Coastguard Worker     // currently have a situation where we need a kUseTail == false SlotFreeList parameter, and 2)
222*795d594fSAndroid Build Coastguard Worker     // supporting the kUseTail == false parameter would require a O(n) linked list traversal to do
223*795d594fSAndroid Build Coastguard Worker     // the merge if 'this' SlotFreeList has kUseTail == false, which we'd like to avoid.
Merge(SlotFreeList<true> * list)224*795d594fSAndroid Build Coastguard Worker     void Merge(SlotFreeList<true>* list) {
225*795d594fSAndroid Build Coastguard Worker       if (kIsDebugBuild) {
226*795d594fSAndroid Build Coastguard Worker         Verify();
227*795d594fSAndroid Build Coastguard Worker         CHECK(list != nullptr);
228*795d594fSAndroid Build Coastguard Worker         list->Verify();
229*795d594fSAndroid Build Coastguard Worker       }
230*795d594fSAndroid Build Coastguard Worker       if (list->Size() == 0) {
231*795d594fSAndroid Build Coastguard Worker         return;
232*795d594fSAndroid Build Coastguard Worker       }
233*795d594fSAndroid Build Coastguard Worker       Slot** headp = reinterpret_cast<Slot**>(&head_);
234*795d594fSAndroid Build Coastguard Worker       Slot** tailp = kUseTail ? reinterpret_cast<Slot**>(&tail_) : nullptr;
235*795d594fSAndroid Build Coastguard Worker       Slot* old_head = *headp;
236*795d594fSAndroid Build Coastguard Worker       if (old_head == nullptr) {
237*795d594fSAndroid Build Coastguard Worker         // List was empty.
238*795d594fSAndroid Build Coastguard Worker         *headp = list->Head();
239*795d594fSAndroid Build Coastguard Worker         if (kUseTail) {
240*795d594fSAndroid Build Coastguard Worker           *tailp = list->Tail();
241*795d594fSAndroid Build Coastguard Worker         }
242*795d594fSAndroid Build Coastguard Worker         size_ = list->Size();
243*795d594fSAndroid Build Coastguard Worker       } else {
244*795d594fSAndroid Build Coastguard Worker         // List wasn't empty.
245*795d594fSAndroid Build Coastguard Worker         DCHECK(list->Head() != nullptr);
246*795d594fSAndroid Build Coastguard Worker         *headp = list->Head();
247*795d594fSAndroid Build Coastguard Worker         DCHECK(list->Tail() != nullptr);
248*795d594fSAndroid Build Coastguard Worker         list->Tail()->SetNext(old_head);
249*795d594fSAndroid Build Coastguard Worker         // if kUseTail, no change to tailp.
250*795d594fSAndroid Build Coastguard Worker         size_ += list->Size();
251*795d594fSAndroid Build Coastguard Worker       }
252*795d594fSAndroid Build Coastguard Worker       list->Reset();
253*795d594fSAndroid Build Coastguard Worker       if (kIsDebugBuild) {
254*795d594fSAndroid Build Coastguard Worker         Verify();
255*795d594fSAndroid Build Coastguard Worker       }
256*795d594fSAndroid Build Coastguard Worker     }
257*795d594fSAndroid Build Coastguard Worker 
Reset()258*795d594fSAndroid Build Coastguard Worker     void Reset() {
259*795d594fSAndroid Build Coastguard Worker       head_ = 0;
260*795d594fSAndroid Build Coastguard Worker       if (kUseTail) {
261*795d594fSAndroid Build Coastguard Worker         tail_ = 0;
262*795d594fSAndroid Build Coastguard Worker       }
263*795d594fSAndroid Build Coastguard Worker       size_ = 0;
264*795d594fSAndroid Build Coastguard Worker     }
265*795d594fSAndroid Build Coastguard Worker 
Verify()266*795d594fSAndroid Build Coastguard Worker     void Verify() {
267*795d594fSAndroid Build Coastguard Worker       Slot* head = reinterpret_cast<Slot*>(head_);
268*795d594fSAndroid Build Coastguard Worker       Slot* tail = kUseTail ? reinterpret_cast<Slot*>(tail_) : nullptr;
269*795d594fSAndroid Build Coastguard Worker       if (size_ == 0) {
270*795d594fSAndroid Build Coastguard Worker         CHECK(head == nullptr);
271*795d594fSAndroid Build Coastguard Worker         if (kUseTail) {
272*795d594fSAndroid Build Coastguard Worker           CHECK(tail == nullptr);
273*795d594fSAndroid Build Coastguard Worker         }
274*795d594fSAndroid Build Coastguard Worker       } else {
275*795d594fSAndroid Build Coastguard Worker         CHECK(head != nullptr);
276*795d594fSAndroid Build Coastguard Worker         if (kUseTail) {
277*795d594fSAndroid Build Coastguard Worker           CHECK(tail != nullptr);
278*795d594fSAndroid Build Coastguard Worker         }
279*795d594fSAndroid Build Coastguard Worker         size_t count = 0;
280*795d594fSAndroid Build Coastguard Worker         for (Slot* slot = head; slot != nullptr; slot = slot->Next()) {
281*795d594fSAndroid Build Coastguard Worker           ++count;
282*795d594fSAndroid Build Coastguard Worker           if (kUseTail && slot->Next() == nullptr) {
283*795d594fSAndroid Build Coastguard Worker             CHECK_EQ(slot, tail);
284*795d594fSAndroid Build Coastguard Worker           }
285*795d594fSAndroid Build Coastguard Worker         }
286*795d594fSAndroid Build Coastguard Worker         CHECK_EQ(size_, count);
287*795d594fSAndroid Build Coastguard Worker       }
288*795d594fSAndroid Build Coastguard Worker     }
289*795d594fSAndroid Build Coastguard Worker 
290*795d594fSAndroid Build Coastguard Worker    private:
291*795d594fSAndroid Build Coastguard Worker     // A pointer (Slot*) to the head of the list. Always 8 bytes so that we will have the same
292*795d594fSAndroid Build Coastguard Worker     // layout between 32 bit and 64 bit, which is not strictly necessary, but we do so for 1)
293*795d594fSAndroid Build Coastguard Worker     // uniformity, 2) we won't need to change this code if we move to a non-low 4G heap in the
294*795d594fSAndroid Build Coastguard Worker     // future, and 3) the space savings by using 32 bit fields in 32 bit would be lost in noise
295*795d594fSAndroid Build Coastguard Worker     // (won't open up enough space to cause an extra slot to be available).
296*795d594fSAndroid Build Coastguard Worker     uint64_t head_;
297*795d594fSAndroid Build Coastguard Worker     // A pointer (Slot*) to the tail of the list. Always 8 bytes so that we will have the same
298*795d594fSAndroid Build Coastguard Worker     // layout between 32 bit and 64 bit. The tail is stored to speed up merging of lists.
299*795d594fSAndroid Build Coastguard Worker     // Unused if kUseTail is false.
300*795d594fSAndroid Build Coastguard Worker     uint64_t tail_;
301*795d594fSAndroid Build Coastguard Worker     // The number of slots in the list. This is used to make it fast to check if a free list is all
302*795d594fSAndroid Build Coastguard Worker     // free without traversing the whole free list.
303*795d594fSAndroid Build Coastguard Worker     uint32_t size_;
304*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] uint32_t padding_;
305*795d594fSAndroid Build Coastguard Worker     friend class RosAlloc;
306*795d594fSAndroid Build Coastguard Worker   };
307*795d594fSAndroid Build Coastguard Worker 
308*795d594fSAndroid Build Coastguard Worker   // Represents a run of memory slots of the same size.
309*795d594fSAndroid Build Coastguard Worker   //
310*795d594fSAndroid Build Coastguard Worker   // A run's memory layout:
311*795d594fSAndroid Build Coastguard Worker   //
312*795d594fSAndroid Build Coastguard Worker   // +-------------------+
313*795d594fSAndroid Build Coastguard Worker   // | magic_num         |
314*795d594fSAndroid Build Coastguard Worker   // +-------------------+
315*795d594fSAndroid Build Coastguard Worker   // | size_bracket_idx  |
316*795d594fSAndroid Build Coastguard Worker   // +-------------------+
317*795d594fSAndroid Build Coastguard Worker   // | is_thread_local   |
318*795d594fSAndroid Build Coastguard Worker   // +-------------------+
319*795d594fSAndroid Build Coastguard Worker   // | to_be_bulk_freed  |
320*795d594fSAndroid Build Coastguard Worker   // +-------------------+
321*795d594fSAndroid Build Coastguard Worker   // |                   |
322*795d594fSAndroid Build Coastguard Worker   // | free list         |
323*795d594fSAndroid Build Coastguard Worker   // |                   |
324*795d594fSAndroid Build Coastguard Worker   // +-------------------+
325*795d594fSAndroid Build Coastguard Worker   // |                   |
326*795d594fSAndroid Build Coastguard Worker   // | bulk free list    |
327*795d594fSAndroid Build Coastguard Worker   // |                   |
328*795d594fSAndroid Build Coastguard Worker   // +-------------------+
329*795d594fSAndroid Build Coastguard Worker   // |                   |
330*795d594fSAndroid Build Coastguard Worker   // | thread-local free |
331*795d594fSAndroid Build Coastguard Worker   // | list              |
332*795d594fSAndroid Build Coastguard Worker   // |                   |
333*795d594fSAndroid Build Coastguard Worker   // +-------------------+
334*795d594fSAndroid Build Coastguard Worker   // | padding due to    |
335*795d594fSAndroid Build Coastguard Worker   // | alignment         |
336*795d594fSAndroid Build Coastguard Worker   // +-------------------+
337*795d594fSAndroid Build Coastguard Worker   // | slot 0            |
338*795d594fSAndroid Build Coastguard Worker   // +-------------------+
339*795d594fSAndroid Build Coastguard Worker   // | slot 1            |
340*795d594fSAndroid Build Coastguard Worker   // +-------------------+
341*795d594fSAndroid Build Coastguard Worker   // | slot 2            |
342*795d594fSAndroid Build Coastguard Worker   // +-------------------+
343*795d594fSAndroid Build Coastguard Worker   // ...
344*795d594fSAndroid Build Coastguard Worker   // +-------------------+
345*795d594fSAndroid Build Coastguard Worker   // | last slot         |
346*795d594fSAndroid Build Coastguard Worker   // +-------------------+
347*795d594fSAndroid Build Coastguard Worker   //
348*795d594fSAndroid Build Coastguard Worker   class Run {
349*795d594fSAndroid Build Coastguard Worker    public:
350*795d594fSAndroid Build Coastguard Worker     uint8_t magic_num_;                 // The magic number used for debugging.
351*795d594fSAndroid Build Coastguard Worker     uint8_t size_bracket_idx_;          // The index of the size bracket of this run.
352*795d594fSAndroid Build Coastguard Worker     uint8_t is_thread_local_;           // True if this run is used as a thread-local run.
353*795d594fSAndroid Build Coastguard Worker     bool to_be_bulk_freed_;             // Used within BulkFree() to flag a run that's involved with
354*795d594fSAndroid Build Coastguard Worker                                         // a bulk free.
355*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] uint32_t padding_;
356*795d594fSAndroid Build Coastguard Worker     // Use a tailless free list for free_list_ so that the alloc fast path does not manage the tail.
357*795d594fSAndroid Build Coastguard Worker     SlotFreeList<false> free_list_;
358*795d594fSAndroid Build Coastguard Worker     SlotFreeList<true> bulk_free_list_;
359*795d594fSAndroid Build Coastguard Worker     SlotFreeList<true> thread_local_free_list_;
360*795d594fSAndroid Build Coastguard Worker     // Padding due to alignment
361*795d594fSAndroid Build Coastguard Worker     // Slot 0
362*795d594fSAndroid Build Coastguard Worker     // Slot 1
363*795d594fSAndroid Build Coastguard Worker     // ...
364*795d594fSAndroid Build Coastguard Worker 
365*795d594fSAndroid Build Coastguard Worker     // Returns the byte size of the header.
fixed_header_size()366*795d594fSAndroid Build Coastguard Worker     static size_t fixed_header_size() {
367*795d594fSAndroid Build Coastguard Worker       return sizeof(Run);
368*795d594fSAndroid Build Coastguard Worker     }
FirstSlot()369*795d594fSAndroid Build Coastguard Worker     Slot* FirstSlot() const {
370*795d594fSAndroid Build Coastguard Worker       const uint8_t idx = size_bracket_idx_;
371*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<Slot*>(reinterpret_cast<uintptr_t>(this) + headerSizes[idx]);
372*795d594fSAndroid Build Coastguard Worker     }
LastSlot()373*795d594fSAndroid Build Coastguard Worker     Slot* LastSlot() {
374*795d594fSAndroid Build Coastguard Worker       const uint8_t idx = size_bracket_idx_;
375*795d594fSAndroid Build Coastguard Worker       const size_t bracket_size = bracketSizes[idx];
376*795d594fSAndroid Build Coastguard Worker       uintptr_t end = reinterpret_cast<uintptr_t>(End());
377*795d594fSAndroid Build Coastguard Worker       Slot* last_slot = reinterpret_cast<Slot*>(end - bracket_size);
378*795d594fSAndroid Build Coastguard Worker       DCHECK_LE(FirstSlot(), last_slot);
379*795d594fSAndroid Build Coastguard Worker       return last_slot;
380*795d594fSAndroid Build Coastguard Worker     }
FreeList()381*795d594fSAndroid Build Coastguard Worker     SlotFreeList<false>* FreeList() {
382*795d594fSAndroid Build Coastguard Worker       return &free_list_;
383*795d594fSAndroid Build Coastguard Worker     }
BulkFreeList()384*795d594fSAndroid Build Coastguard Worker     SlotFreeList<true>* BulkFreeList() {
385*795d594fSAndroid Build Coastguard Worker       return &bulk_free_list_;
386*795d594fSAndroid Build Coastguard Worker     }
ThreadLocalFreeList()387*795d594fSAndroid Build Coastguard Worker     SlotFreeList<true>* ThreadLocalFreeList() {
388*795d594fSAndroid Build Coastguard Worker       return &thread_local_free_list_;
389*795d594fSAndroid Build Coastguard Worker     }
End()390*795d594fSAndroid Build Coastguard Worker     void* End() {
391*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<uint8_t*>(this) + gPageSize * numOfPages[size_bracket_idx_];
392*795d594fSAndroid Build Coastguard Worker     }
SetIsThreadLocal(bool is_thread_local)393*795d594fSAndroid Build Coastguard Worker     void SetIsThreadLocal(bool is_thread_local) {
394*795d594fSAndroid Build Coastguard Worker       is_thread_local_  = is_thread_local ? 1 : 0;
395*795d594fSAndroid Build Coastguard Worker     }
IsThreadLocal()396*795d594fSAndroid Build Coastguard Worker     bool IsThreadLocal() const {
397*795d594fSAndroid Build Coastguard Worker       return is_thread_local_ != 0;
398*795d594fSAndroid Build Coastguard Worker     }
399*795d594fSAndroid Build Coastguard Worker     // Set up the free list for a new/empty run.
InitFreeList()400*795d594fSAndroid Build Coastguard Worker     void InitFreeList() {
401*795d594fSAndroid Build Coastguard Worker       const uint8_t idx = size_bracket_idx_;
402*795d594fSAndroid Build Coastguard Worker       const size_t bracket_size = bracketSizes[idx];
403*795d594fSAndroid Build Coastguard Worker       Slot* first_slot = FirstSlot();
404*795d594fSAndroid Build Coastguard Worker       // Add backwards so the first slot is at the head of the list.
405*795d594fSAndroid Build Coastguard Worker       for (Slot* slot = LastSlot(); slot >= first_slot; slot = slot->Left(bracket_size)) {
406*795d594fSAndroid Build Coastguard Worker         free_list_.Add(slot);
407*795d594fSAndroid Build Coastguard Worker       }
408*795d594fSAndroid Build Coastguard Worker     }
409*795d594fSAndroid Build Coastguard Worker     // Merge the thread local free list to the free list.  Used when a thread-local run becomes
410*795d594fSAndroid Build Coastguard Worker     // full.
411*795d594fSAndroid Build Coastguard Worker     bool MergeThreadLocalFreeListToFreeList(bool* is_all_free_after_out);
412*795d594fSAndroid Build Coastguard Worker     // Merge the bulk free list to the free list. Used in a bulk free.
413*795d594fSAndroid Build Coastguard Worker     void MergeBulkFreeListToFreeList();
414*795d594fSAndroid Build Coastguard Worker     // Merge the bulk free list to the thread local free list. In a bulk free, as a two-step
415*795d594fSAndroid Build Coastguard Worker     // process, GC will first record all the slots to free in a run in the bulk free list where it
416*795d594fSAndroid Build Coastguard Worker     // can write without a lock, and later acquire a lock once per run to merge the bulk free list
417*795d594fSAndroid Build Coastguard Worker     // to the thread-local free list.
418*795d594fSAndroid Build Coastguard Worker     void MergeBulkFreeListToThreadLocalFreeList();
419*795d594fSAndroid Build Coastguard Worker     // Allocates a slot in a run.
420*795d594fSAndroid Build Coastguard Worker     ALWAYS_INLINE void* AllocSlot();
421*795d594fSAndroid Build Coastguard Worker     // Frees a slot in a run. This is used in a non-bulk free.
422*795d594fSAndroid Build Coastguard Worker     void FreeSlot(void* ptr);
423*795d594fSAndroid Build Coastguard Worker     // Add the given slot to the bulk free list. Returns the bracket size.
424*795d594fSAndroid Build Coastguard Worker     size_t AddToBulkFreeList(void* ptr);
425*795d594fSAndroid Build Coastguard Worker     // Add the given slot to the thread-local free list.
426*795d594fSAndroid Build Coastguard Worker     void AddToThreadLocalFreeList(void* ptr);
427*795d594fSAndroid Build Coastguard Worker     // Returns true if all the slots in the run are not in use.
IsAllFree()428*795d594fSAndroid Build Coastguard Worker     bool IsAllFree() const {
429*795d594fSAndroid Build Coastguard Worker       return free_list_.Size() == numOfSlots[size_bracket_idx_];
430*795d594fSAndroid Build Coastguard Worker     }
431*795d594fSAndroid Build Coastguard Worker     // Returns the number of free slots.
NumberOfFreeSlots()432*795d594fSAndroid Build Coastguard Worker     size_t NumberOfFreeSlots() {
433*795d594fSAndroid Build Coastguard Worker       return free_list_.Size();
434*795d594fSAndroid Build Coastguard Worker     }
435*795d594fSAndroid Build Coastguard Worker     // Returns true if all the slots in the run are in use.
436*795d594fSAndroid Build Coastguard Worker     ALWAYS_INLINE bool IsFull();
437*795d594fSAndroid Build Coastguard Worker     // Returns true if the bulk free list is empty.
IsBulkFreeListEmpty()438*795d594fSAndroid Build Coastguard Worker     bool IsBulkFreeListEmpty() const {
439*795d594fSAndroid Build Coastguard Worker       return bulk_free_list_.Size() == 0;
440*795d594fSAndroid Build Coastguard Worker     }
441*795d594fSAndroid Build Coastguard Worker     // Returns true if the thread local free list is empty.
IsThreadLocalFreeListEmpty()442*795d594fSAndroid Build Coastguard Worker     bool IsThreadLocalFreeListEmpty() const {
443*795d594fSAndroid Build Coastguard Worker       return thread_local_free_list_.Size() == 0;
444*795d594fSAndroid Build Coastguard Worker     }
445*795d594fSAndroid Build Coastguard Worker     // Zero the run's data.
446*795d594fSAndroid Build Coastguard Worker     void ZeroData();
447*795d594fSAndroid Build Coastguard Worker     // Zero the run's header and the slot headers.
448*795d594fSAndroid Build Coastguard Worker     void ZeroHeaderAndSlotHeaders();
449*795d594fSAndroid Build Coastguard Worker     // Iterate over all the slots and apply the given function.
450*795d594fSAndroid Build Coastguard Worker     void InspectAllSlots(void (*handler)(void* start, void* end, size_t used_bytes, void* callback_arg), void* arg);
451*795d594fSAndroid Build Coastguard Worker     // Dump the run metadata for debugging.
452*795d594fSAndroid Build Coastguard Worker     std::string Dump();
453*795d594fSAndroid Build Coastguard Worker     // Verify for debugging.
454*795d594fSAndroid Build Coastguard Worker     void Verify(Thread* self, RosAlloc* rosalloc, bool running_on_memory_tool)
455*795d594fSAndroid Build Coastguard Worker         REQUIRES(Locks::mutator_lock_)
456*795d594fSAndroid Build Coastguard Worker         REQUIRES(Locks::thread_list_lock_);
457*795d594fSAndroid Build Coastguard Worker 
458*795d594fSAndroid Build Coastguard Worker    private:
459*795d594fSAndroid Build Coastguard Worker     // The common part of AddToBulkFreeList() and AddToThreadLocalFreeList(). Returns the bracket
460*795d594fSAndroid Build Coastguard Worker     // size.
461*795d594fSAndroid Build Coastguard Worker     size_t AddToFreeListShared(void* ptr, SlotFreeList<true>* free_list, const char* caller_name);
462*795d594fSAndroid Build Coastguard Worker     // Turns a FreeList into a string for debugging.
463*795d594fSAndroid Build Coastguard Worker     template<bool kUseTail>
464*795d594fSAndroid Build Coastguard Worker     std::string FreeListToStr(SlotFreeList<kUseTail>* free_list);
465*795d594fSAndroid Build Coastguard Worker     // Check a given pointer is a valid slot address and return it as Slot*.
ToSlot(void * ptr)466*795d594fSAndroid Build Coastguard Worker     Slot* ToSlot(void* ptr) {
467*795d594fSAndroid Build Coastguard Worker       const uint8_t idx = size_bracket_idx_;
468*795d594fSAndroid Build Coastguard Worker       const size_t bracket_size = bracketSizes[idx];
469*795d594fSAndroid Build Coastguard Worker       const size_t offset_from_slot_base = reinterpret_cast<uint8_t*>(ptr)
470*795d594fSAndroid Build Coastguard Worker           - reinterpret_cast<uint8_t*>(FirstSlot());
471*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(offset_from_slot_base % bracket_size, static_cast<size_t>(0));
472*795d594fSAndroid Build Coastguard Worker       size_t slot_idx = offset_from_slot_base / bracket_size;
473*795d594fSAndroid Build Coastguard Worker       DCHECK_LT(slot_idx, numOfSlots[idx]);
474*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<Slot*>(ptr);
475*795d594fSAndroid Build Coastguard Worker     }
SlotIndex(Slot * slot)476*795d594fSAndroid Build Coastguard Worker     size_t SlotIndex(Slot* slot) const {
477*795d594fSAndroid Build Coastguard Worker       const uint8_t idx = size_bracket_idx_;
478*795d594fSAndroid Build Coastguard Worker       const size_t bracket_size = bracketSizes[idx];
479*795d594fSAndroid Build Coastguard Worker       const size_t offset_from_slot_base = reinterpret_cast<uint8_t*>(slot)
480*795d594fSAndroid Build Coastguard Worker           - reinterpret_cast<uint8_t*>(FirstSlot());
481*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(offset_from_slot_base % bracket_size, 0U);
482*795d594fSAndroid Build Coastguard Worker       size_t slot_idx = offset_from_slot_base / bracket_size;
483*795d594fSAndroid Build Coastguard Worker       DCHECK_LT(slot_idx, numOfSlots[idx]);
484*795d594fSAndroid Build Coastguard Worker       return slot_idx;
485*795d594fSAndroid Build Coastguard Worker     }
486*795d594fSAndroid Build Coastguard Worker 
487*795d594fSAndroid Build Coastguard Worker     // TODO: DISALLOW_COPY_AND_ASSIGN(Run);
488*795d594fSAndroid Build Coastguard Worker   };
489*795d594fSAndroid Build Coastguard Worker 
490*795d594fSAndroid Build Coastguard Worker   // The magic number for a run.
491*795d594fSAndroid Build Coastguard Worker   static constexpr uint8_t kMagicNum = 42;
492*795d594fSAndroid Build Coastguard Worker   // The magic number for free pages.
493*795d594fSAndroid Build Coastguard Worker   static constexpr uint8_t kMagicNumFree = 43;
494*795d594fSAndroid Build Coastguard Worker   // The number of size brackets.
495*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumOfSizeBrackets = 42;
496*795d594fSAndroid Build Coastguard Worker   // The sizes (the slot sizes, in bytes) of the size brackets.
497*795d594fSAndroid Build Coastguard Worker   static size_t bracketSizes[kNumOfSizeBrackets];
498*795d594fSAndroid Build Coastguard Worker   // The numbers of pages that are used for runs for each size bracket.
499*795d594fSAndroid Build Coastguard Worker   static size_t numOfPages[kNumOfSizeBrackets];
500*795d594fSAndroid Build Coastguard Worker   // The numbers of slots of the runs for each size bracket.
501*795d594fSAndroid Build Coastguard Worker   EXPORT static size_t numOfSlots[kNumOfSizeBrackets];
502*795d594fSAndroid Build Coastguard Worker   // The header sizes in bytes of the runs for each size bracket.
503*795d594fSAndroid Build Coastguard Worker   static size_t headerSizes[kNumOfSizeBrackets];
504*795d594fSAndroid Build Coastguard Worker 
505*795d594fSAndroid Build Coastguard Worker   // Initialize the run specs (the above arrays).
506*795d594fSAndroid Build Coastguard Worker   static void Initialize();
507*795d594fSAndroid Build Coastguard Worker   static bool initialized_;
508*795d594fSAndroid Build Coastguard Worker 
509*795d594fSAndroid Build Coastguard Worker   // Returns the byte size of the bracket size from the index.
IndexToBracketSize(size_t idx)510*795d594fSAndroid Build Coastguard Worker   static size_t IndexToBracketSize(size_t idx) {
511*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(idx, kNumOfSizeBrackets);
512*795d594fSAndroid Build Coastguard Worker     return bracketSizes[idx];
513*795d594fSAndroid Build Coastguard Worker   }
514*795d594fSAndroid Build Coastguard Worker   // Returns the index of the size bracket from the bracket size.
BracketSizeToIndex(size_t size)515*795d594fSAndroid Build Coastguard Worker   static size_t BracketSizeToIndex(size_t size) {
516*795d594fSAndroid Build Coastguard Worker     DCHECK(8 <= size &&
517*795d594fSAndroid Build Coastguard Worker            ((size <= kMaxThreadLocalBracketSize && size % kThreadLocalBracketQuantumSize == 0) ||
518*795d594fSAndroid Build Coastguard Worker             (size <= kMaxRegularBracketSize && size % kBracketQuantumSize == 0) ||
519*795d594fSAndroid Build Coastguard Worker             size == 1 * KB || size == 2 * KB));
520*795d594fSAndroid Build Coastguard Worker     size_t idx;
521*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(size == 1 * KB)) {
522*795d594fSAndroid Build Coastguard Worker       idx = kNumOfSizeBrackets - 2;
523*795d594fSAndroid Build Coastguard Worker     } else if (UNLIKELY(size == 2 * KB)) {
524*795d594fSAndroid Build Coastguard Worker       idx = kNumOfSizeBrackets - 1;
525*795d594fSAndroid Build Coastguard Worker     } else if (LIKELY(size <= kMaxThreadLocalBracketSize)) {
526*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(size % kThreadLocalBracketQuantumSize, 0U);
527*795d594fSAndroid Build Coastguard Worker       idx = size / kThreadLocalBracketQuantumSize - 1;
528*795d594fSAndroid Build Coastguard Worker     } else {
529*795d594fSAndroid Build Coastguard Worker       DCHECK(size <= kMaxRegularBracketSize);
530*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ((size - kMaxThreadLocalBracketSize) % kBracketQuantumSize, 0U);
531*795d594fSAndroid Build Coastguard Worker       idx = ((size - kMaxThreadLocalBracketSize) / kBracketQuantumSize - 1)
532*795d594fSAndroid Build Coastguard Worker           + kNumThreadLocalSizeBrackets;
533*795d594fSAndroid Build Coastguard Worker     }
534*795d594fSAndroid Build Coastguard Worker     DCHECK(bracketSizes[idx] == size);
535*795d594fSAndroid Build Coastguard Worker     return idx;
536*795d594fSAndroid Build Coastguard Worker   }
537*795d594fSAndroid Build Coastguard Worker   // Returns true if the given allocation size is for a thread local allocation.
IsSizeForThreadLocal(size_t size)538*795d594fSAndroid Build Coastguard Worker   static bool IsSizeForThreadLocal(size_t size) {
539*795d594fSAndroid Build Coastguard Worker     bool is_size_for_thread_local = size <= kMaxThreadLocalBracketSize;
540*795d594fSAndroid Build Coastguard Worker     DCHECK(size > kLargeSizeThreshold ||
541*795d594fSAndroid Build Coastguard Worker            (is_size_for_thread_local == (SizeToIndex(size) < kNumThreadLocalSizeBrackets)));
542*795d594fSAndroid Build Coastguard Worker     return is_size_for_thread_local;
543*795d594fSAndroid Build Coastguard Worker   }
544*795d594fSAndroid Build Coastguard Worker   // Rounds up the size up the nearest bracket size.
RoundToBracketSize(size_t size)545*795d594fSAndroid Build Coastguard Worker   static size_t RoundToBracketSize(size_t size) {
546*795d594fSAndroid Build Coastguard Worker     DCHECK(size <= kLargeSizeThreshold);
547*795d594fSAndroid Build Coastguard Worker     if (LIKELY(size <= kMaxThreadLocalBracketSize)) {
548*795d594fSAndroid Build Coastguard Worker       return RoundUp(size, kThreadLocalBracketQuantumSize);
549*795d594fSAndroid Build Coastguard Worker     } else if (size <= kMaxRegularBracketSize) {
550*795d594fSAndroid Build Coastguard Worker       return RoundUp(size, kBracketQuantumSize);
551*795d594fSAndroid Build Coastguard Worker     } else if (UNLIKELY(size <= 1 * KB)) {
552*795d594fSAndroid Build Coastguard Worker       return 1 * KB;
553*795d594fSAndroid Build Coastguard Worker     } else {
554*795d594fSAndroid Build Coastguard Worker       DCHECK_LE(size, 2 * KB);
555*795d594fSAndroid Build Coastguard Worker       return 2 * KB;
556*795d594fSAndroid Build Coastguard Worker     }
557*795d594fSAndroid Build Coastguard Worker   }
558*795d594fSAndroid Build Coastguard Worker   // Returns the size bracket index from the byte size with rounding.
SizeToIndex(size_t size)559*795d594fSAndroid Build Coastguard Worker   static size_t SizeToIndex(size_t size) {
560*795d594fSAndroid Build Coastguard Worker     DCHECK(size <= kLargeSizeThreshold);
561*795d594fSAndroid Build Coastguard Worker     if (LIKELY(size <= kMaxThreadLocalBracketSize)) {
562*795d594fSAndroid Build Coastguard Worker       return RoundUp(size, kThreadLocalBracketQuantumSize) / kThreadLocalBracketQuantumSize - 1;
563*795d594fSAndroid Build Coastguard Worker     } else if (size <= kMaxRegularBracketSize) {
564*795d594fSAndroid Build Coastguard Worker       return (RoundUp(size, kBracketQuantumSize) - kMaxThreadLocalBracketSize) / kBracketQuantumSize
565*795d594fSAndroid Build Coastguard Worker           - 1 + kNumThreadLocalSizeBrackets;
566*795d594fSAndroid Build Coastguard Worker     } else if (size <= 1 * KB) {
567*795d594fSAndroid Build Coastguard Worker       return kNumOfSizeBrackets - 2;
568*795d594fSAndroid Build Coastguard Worker     } else {
569*795d594fSAndroid Build Coastguard Worker       DCHECK_LE(size, 2 * KB);
570*795d594fSAndroid Build Coastguard Worker       return kNumOfSizeBrackets - 1;
571*795d594fSAndroid Build Coastguard Worker     }
572*795d594fSAndroid Build Coastguard Worker   }
573*795d594fSAndroid Build Coastguard Worker   // A combination of SizeToIndex() and RoundToBracketSize().
SizeToIndexAndBracketSize(size_t size,size_t * bracket_size_out)574*795d594fSAndroid Build Coastguard Worker   static size_t SizeToIndexAndBracketSize(size_t size, size_t* bracket_size_out) {
575*795d594fSAndroid Build Coastguard Worker     DCHECK(size <= kLargeSizeThreshold);
576*795d594fSAndroid Build Coastguard Worker     size_t idx;
577*795d594fSAndroid Build Coastguard Worker     size_t bracket_size;
578*795d594fSAndroid Build Coastguard Worker     if (LIKELY(size <= kMaxThreadLocalBracketSize)) {
579*795d594fSAndroid Build Coastguard Worker       bracket_size = RoundUp(size, kThreadLocalBracketQuantumSize);
580*795d594fSAndroid Build Coastguard Worker       idx = bracket_size / kThreadLocalBracketQuantumSize - 1;
581*795d594fSAndroid Build Coastguard Worker     } else if (size <= kMaxRegularBracketSize) {
582*795d594fSAndroid Build Coastguard Worker       bracket_size = RoundUp(size, kBracketQuantumSize);
583*795d594fSAndroid Build Coastguard Worker       idx = ((bracket_size - kMaxThreadLocalBracketSize) / kBracketQuantumSize - 1)
584*795d594fSAndroid Build Coastguard Worker           + kNumThreadLocalSizeBrackets;
585*795d594fSAndroid Build Coastguard Worker     } else if (size <= 1 * KB) {
586*795d594fSAndroid Build Coastguard Worker       bracket_size = 1 * KB;
587*795d594fSAndroid Build Coastguard Worker       idx = kNumOfSizeBrackets - 2;
588*795d594fSAndroid Build Coastguard Worker     } else {
589*795d594fSAndroid Build Coastguard Worker       DCHECK(size <= 2 * KB);
590*795d594fSAndroid Build Coastguard Worker       bracket_size = 2 * KB;
591*795d594fSAndroid Build Coastguard Worker       idx = kNumOfSizeBrackets - 1;
592*795d594fSAndroid Build Coastguard Worker     }
593*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(idx, SizeToIndex(size)) << idx;
594*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(bracket_size, IndexToBracketSize(idx)) << idx;
595*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(bracket_size, bracketSizes[idx]) << idx;
596*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(size, bracket_size) << idx;
597*795d594fSAndroid Build Coastguard Worker     DCHECK(size > kMaxRegularBracketSize ||
598*795d594fSAndroid Build Coastguard Worker            (size <= kMaxThreadLocalBracketSize &&
599*795d594fSAndroid Build Coastguard Worker             bracket_size - size < kThreadLocalBracketQuantumSize) ||
600*795d594fSAndroid Build Coastguard Worker            (size <= kMaxRegularBracketSize && bracket_size - size < kBracketQuantumSize)) << idx;
601*795d594fSAndroid Build Coastguard Worker     *bracket_size_out = bracket_size;
602*795d594fSAndroid Build Coastguard Worker     return idx;
603*795d594fSAndroid Build Coastguard Worker   }
604*795d594fSAndroid Build Coastguard Worker 
605*795d594fSAndroid Build Coastguard Worker   // Returns the page map index from an address. Requires that the
606*795d594fSAndroid Build Coastguard Worker   // address is page size aligned.
ToPageMapIndex(const void * addr)607*795d594fSAndroid Build Coastguard Worker   size_t ToPageMapIndex(const void* addr) const {
608*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(base_, addr);
609*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(addr, base_ + capacity_);
610*795d594fSAndroid Build Coastguard Worker     size_t byte_offset = reinterpret_cast<const uint8_t*>(addr) - base_;
611*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(ModuloPageSize(byte_offset), static_cast<size_t>(0));
612*795d594fSAndroid Build Coastguard Worker     return DivideByPageSize(byte_offset);
613*795d594fSAndroid Build Coastguard Worker   }
614*795d594fSAndroid Build Coastguard Worker   // Returns the page map index from an address with rounding.
RoundDownToPageMapIndex(const void * addr)615*795d594fSAndroid Build Coastguard Worker   size_t RoundDownToPageMapIndex(const void* addr) const {
616*795d594fSAndroid Build Coastguard Worker     DCHECK(base_ <= addr && addr < reinterpret_cast<uint8_t*>(base_) + capacity_);
617*795d594fSAndroid Build Coastguard Worker     return DivideByPageSize(reinterpret_cast<uintptr_t>(addr) - reinterpret_cast<uintptr_t>(base_));
618*795d594fSAndroid Build Coastguard Worker   }
619*795d594fSAndroid Build Coastguard Worker 
620*795d594fSAndroid Build Coastguard Worker   // A memory allocation request larger than this size is treated as a large object and allocated
621*795d594fSAndroid Build Coastguard Worker   // at a page-granularity.
622*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kLargeSizeThreshold = 2048;
623*795d594fSAndroid Build Coastguard Worker 
624*795d594fSAndroid Build Coastguard Worker   // If true, check that the returned memory is actually zero.
625*795d594fSAndroid Build Coastguard Worker   static constexpr bool kCheckZeroMemory = kIsDebugBuild;
626*795d594fSAndroid Build Coastguard Worker   // Do not check memory when running under a memory tool. In a normal
627*795d594fSAndroid Build Coastguard Worker   // build with kCheckZeroMemory the whole test should be optimized away.
628*795d594fSAndroid Build Coastguard Worker   // TODO: Unprotect before checks.
629*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool ShouldCheckZeroMemory();
630*795d594fSAndroid Build Coastguard Worker 
631*795d594fSAndroid Build Coastguard Worker   // If true, log verbose details of operations.
632*795d594fSAndroid Build Coastguard Worker   static constexpr bool kTraceRosAlloc = false;
633*795d594fSAndroid Build Coastguard Worker 
634*795d594fSAndroid Build Coastguard Worker   struct hash_run {
operatorhash_run635*795d594fSAndroid Build Coastguard Worker     size_t operator()(const RosAlloc::Run* r) const {
636*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<size_t>(r);
637*795d594fSAndroid Build Coastguard Worker     }
638*795d594fSAndroid Build Coastguard Worker   };
639*795d594fSAndroid Build Coastguard Worker 
640*795d594fSAndroid Build Coastguard Worker   struct eq_run {
operatoreq_run641*795d594fSAndroid Build Coastguard Worker     bool operator()(const RosAlloc::Run* r1, const RosAlloc::Run* r2) const {
642*795d594fSAndroid Build Coastguard Worker       return r1 == r2;
643*795d594fSAndroid Build Coastguard Worker     }
644*795d594fSAndroid Build Coastguard Worker   };
645*795d594fSAndroid Build Coastguard Worker 
646*795d594fSAndroid Build Coastguard Worker  public:
647*795d594fSAndroid Build Coastguard Worker   // Different page release modes.
648*795d594fSAndroid Build Coastguard Worker   enum PageReleaseMode {
649*795d594fSAndroid Build Coastguard Worker     kPageReleaseModeNone,         // Release no empty pages.
650*795d594fSAndroid Build Coastguard Worker     kPageReleaseModeEnd,          // Release empty pages at the end of the space.
651*795d594fSAndroid Build Coastguard Worker     kPageReleaseModeSize,         // Release empty pages that are larger than the threshold.
652*795d594fSAndroid Build Coastguard Worker     kPageReleaseModeSizeAndEnd,   // Release empty pages that are larger than the threshold or
653*795d594fSAndroid Build Coastguard Worker                                   // at the end of the space.
654*795d594fSAndroid Build Coastguard Worker     kPageReleaseModeAll,          // Release all empty pages.
655*795d594fSAndroid Build Coastguard Worker   };
656*795d594fSAndroid Build Coastguard Worker 
657*795d594fSAndroid Build Coastguard Worker   // The default value for page_release_size_threshold_.
658*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kDefaultPageReleaseSizeThreshold = 4 * MB;
659*795d594fSAndroid Build Coastguard Worker 
660*795d594fSAndroid Build Coastguard Worker   // We use thread-local runs for the size brackets whose indexes
661*795d594fSAndroid Build Coastguard Worker   // are less than this index. We use shared (current) runs for the rest.
662*795d594fSAndroid Build Coastguard Worker   // Sync this with the length of Thread::rosalloc_runs_.
663*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumThreadLocalSizeBrackets = 16;
664*795d594fSAndroid Build Coastguard Worker   static_assert(kNumThreadLocalSizeBrackets == kNumRosAllocThreadLocalSizeBracketsInThread,
665*795d594fSAndroid Build Coastguard Worker                 "Mismatch between kNumThreadLocalSizeBrackets and "
666*795d594fSAndroid Build Coastguard Worker                 "kNumRosAllocThreadLocalSizeBracketsInThread");
667*795d594fSAndroid Build Coastguard Worker 
668*795d594fSAndroid Build Coastguard Worker   // The size of the largest bracket we use thread-local runs for.
669*795d594fSAndroid Build Coastguard Worker   // This should be equal to bracketSizes[kNumThreadLocalSizeBrackets - 1].
670*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kMaxThreadLocalBracketSize = 128;
671*795d594fSAndroid Build Coastguard Worker 
672*795d594fSAndroid Build Coastguard Worker   // We use regular (8 or 16-bytes increment) runs for the size brackets whose indexes are less than
673*795d594fSAndroid Build Coastguard Worker   // this index.
674*795d594fSAndroid Build Coastguard Worker   static const size_t kNumRegularSizeBrackets = 40;
675*795d594fSAndroid Build Coastguard Worker 
676*795d594fSAndroid Build Coastguard Worker   // The size of the largest regular (8 or 16-byte increment) bracket. Non-regular brackets are the
677*795d594fSAndroid Build Coastguard Worker   // 1 KB and the 2 KB brackets. This should be equal to bracketSizes[kNumRegularSizeBrackets - 1].
678*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kMaxRegularBracketSize = 512;
679*795d594fSAndroid Build Coastguard Worker 
680*795d594fSAndroid Build Coastguard Worker   // The bracket size increment for the thread-local brackets (<= kMaxThreadLocalBracketSize bytes).
681*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kThreadLocalBracketQuantumSize = 8;
682*795d594fSAndroid Build Coastguard Worker 
683*795d594fSAndroid Build Coastguard Worker   // Equal to Log2(kThreadLocalBracketQuantumSize).
684*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kThreadLocalBracketQuantumSizeShift = 3;
685*795d594fSAndroid Build Coastguard Worker 
686*795d594fSAndroid Build Coastguard Worker   // The bracket size increment for the non-thread-local, regular brackets (of size <=
687*795d594fSAndroid Build Coastguard Worker   // kMaxRegularBracketSize bytes and > kMaxThreadLocalBracketSize bytes).
688*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kBracketQuantumSize = 16;
689*795d594fSAndroid Build Coastguard Worker 
690*795d594fSAndroid Build Coastguard Worker   // Equal to Log2(kBracketQuantumSize).
691*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kBracketQuantumSizeShift = 4;
692*795d594fSAndroid Build Coastguard Worker 
693*795d594fSAndroid Build Coastguard Worker  private:
694*795d594fSAndroid Build Coastguard Worker   // The base address of the memory region that's managed by this allocator.
695*795d594fSAndroid Build Coastguard Worker   uint8_t* base_;
696*795d594fSAndroid Build Coastguard Worker 
697*795d594fSAndroid Build Coastguard Worker   // The footprint in bytes of the currently allocated portion of the
698*795d594fSAndroid Build Coastguard Worker   // memory region.
699*795d594fSAndroid Build Coastguard Worker   size_t footprint_;
700*795d594fSAndroid Build Coastguard Worker 
701*795d594fSAndroid Build Coastguard Worker   // The maximum footprint. The address, base_ + capacity_, indicates
702*795d594fSAndroid Build Coastguard Worker   // the end of the memory region that's currently managed by this allocator.
703*795d594fSAndroid Build Coastguard Worker   size_t capacity_;
704*795d594fSAndroid Build Coastguard Worker 
705*795d594fSAndroid Build Coastguard Worker   // The maximum capacity. The address, base_ + max_capacity_, indicates
706*795d594fSAndroid Build Coastguard Worker   // the end of the memory region that's ever managed by this allocator.
707*795d594fSAndroid Build Coastguard Worker   size_t max_capacity_;
708*795d594fSAndroid Build Coastguard Worker 
709*795d594fSAndroid Build Coastguard Worker   template<class Key, AllocatorTag kTag, class Compare = std::less<Key>>
710*795d594fSAndroid Build Coastguard Worker   using AllocationTrackingSet = std::set<Key, Compare, TrackingAllocator<Key, kTag>>;
711*795d594fSAndroid Build Coastguard Worker 
712*795d594fSAndroid Build Coastguard Worker   // The run sets that hold the runs whose slots are not all
713*795d594fSAndroid Build Coastguard Worker   // full. non_full_runs_[i] is guarded by size_bracket_locks_[i].
714*795d594fSAndroid Build Coastguard Worker   AllocationTrackingSet<Run*, kAllocatorTagRosAlloc> non_full_runs_[kNumOfSizeBrackets];
715*795d594fSAndroid Build Coastguard Worker   // The run sets that hold the runs whose slots are all full. This is
716*795d594fSAndroid Build Coastguard Worker   // debug only. full_runs_[i] is guarded by size_bracket_locks_[i].
717*795d594fSAndroid Build Coastguard Worker   std::unordered_set<Run*, hash_run, eq_run, TrackingAllocator<Run*, kAllocatorTagRosAlloc>>
718*795d594fSAndroid Build Coastguard Worker       full_runs_[kNumOfSizeBrackets];
719*795d594fSAndroid Build Coastguard Worker   // The set of free pages.
720*795d594fSAndroid Build Coastguard Worker   AllocationTrackingSet<FreePageRun*, kAllocatorTagRosAlloc> free_page_runs_ GUARDED_BY(lock_);
721*795d594fSAndroid Build Coastguard Worker   // The dedicated full run, it is always full and shared by all threads when revoking happens.
722*795d594fSAndroid Build Coastguard Worker   // This is an optimization since enables us to avoid a null check for revoked runs.
723*795d594fSAndroid Build Coastguard Worker   static Run* dedicated_full_run_;
724*795d594fSAndroid Build Coastguard Worker   // Using size_t to ensure that it is at least word aligned.
725*795d594fSAndroid Build Coastguard Worker   static size_t dedicated_full_run_storage_[];
726*795d594fSAndroid Build Coastguard Worker   // The current runs where the allocations are first attempted for
727*795d594fSAndroid Build Coastguard Worker   // the size brackes that do not use thread-local
728*795d594fSAndroid Build Coastguard Worker   // runs. current_runs_[i] is guarded by size_bracket_locks_[i].
729*795d594fSAndroid Build Coastguard Worker   Run* current_runs_[kNumOfSizeBrackets];
730*795d594fSAndroid Build Coastguard Worker   // The mutexes, one per size bracket.
731*795d594fSAndroid Build Coastguard Worker   Mutex* size_bracket_locks_[kNumOfSizeBrackets];
732*795d594fSAndroid Build Coastguard Worker   // Bracket lock names (since locks only have char* names).
733*795d594fSAndroid Build Coastguard Worker   std::string size_bracket_lock_names_[kNumOfSizeBrackets];
734*795d594fSAndroid Build Coastguard Worker   // The types of page map entries.
735*795d594fSAndroid Build Coastguard Worker   enum PageMapKind {
736*795d594fSAndroid Build Coastguard Worker     kPageMapReleased = 0,     // Zero and released back to the OS.
737*795d594fSAndroid Build Coastguard Worker     kPageMapEmpty,            // Zero but probably dirty.
738*795d594fSAndroid Build Coastguard Worker     kPageMapRun,              // The beginning of a run.
739*795d594fSAndroid Build Coastguard Worker     kPageMapRunPart,          // The non-beginning part of a run.
740*795d594fSAndroid Build Coastguard Worker     kPageMapLargeObject,      // The beginning of a large object.
741*795d594fSAndroid Build Coastguard Worker     kPageMapLargeObjectPart,  // The non-beginning part of a large object.
742*795d594fSAndroid Build Coastguard Worker   };
743*795d594fSAndroid Build Coastguard Worker   // The table that indicates what pages are currently used for.
744*795d594fSAndroid Build Coastguard Worker   volatile uint8_t* page_map_;  // No GUARDED_BY(lock_) for kReadPageMapEntryWithoutLockInBulkFree.
745*795d594fSAndroid Build Coastguard Worker   size_t page_map_size_;
746*795d594fSAndroid Build Coastguard Worker   size_t max_page_map_size_;
747*795d594fSAndroid Build Coastguard Worker   MemMap page_map_mem_map_;
748*795d594fSAndroid Build Coastguard Worker 
749*795d594fSAndroid Build Coastguard Worker   // The table that indicates the size of free page runs. These sizes
750*795d594fSAndroid Build Coastguard Worker   // are stored here to avoid storing in the free page header and
751*795d594fSAndroid Build Coastguard Worker   // release backing pages.
752*795d594fSAndroid Build Coastguard Worker   std::vector<size_t, TrackingAllocator<size_t, kAllocatorTagRosAlloc>> free_page_run_size_map_
753*795d594fSAndroid Build Coastguard Worker       GUARDED_BY(lock_);
754*795d594fSAndroid Build Coastguard Worker   // The global lock. Used to guard the page map, the free page set,
755*795d594fSAndroid Build Coastguard Worker   // and the footprint.
756*795d594fSAndroid Build Coastguard Worker   Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
757*795d594fSAndroid Build Coastguard Worker   // The reader-writer lock to allow one bulk free at a time while
758*795d594fSAndroid Build Coastguard Worker   // allowing multiple individual frees at the same time. Also, this
759*795d594fSAndroid Build Coastguard Worker   // is used to avoid race conditions between BulkFree() and
760*795d594fSAndroid Build Coastguard Worker   // RevokeThreadLocalRuns() on the bulk free list.
761*795d594fSAndroid Build Coastguard Worker   ReaderWriterMutex bulk_free_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
762*795d594fSAndroid Build Coastguard Worker 
763*795d594fSAndroid Build Coastguard Worker   // The page release mode.
764*795d594fSAndroid Build Coastguard Worker   const PageReleaseMode page_release_mode_;
765*795d594fSAndroid Build Coastguard Worker   // Under kPageReleaseModeSize(AndEnd), if the free page run size is
766*795d594fSAndroid Build Coastguard Worker   // greater than or equal to this value, release pages.
767*795d594fSAndroid Build Coastguard Worker   const size_t page_release_size_threshold_;
768*795d594fSAndroid Build Coastguard Worker 
769*795d594fSAndroid Build Coastguard Worker   // Whether this allocator is running on a memory tool.
770*795d594fSAndroid Build Coastguard Worker   bool is_running_on_memory_tool_;
771*795d594fSAndroid Build Coastguard Worker 
772*795d594fSAndroid Build Coastguard Worker   // The base address of the memory region that's managed by this allocator.
Begin()773*795d594fSAndroid Build Coastguard Worker   uint8_t* Begin() { return base_; }
774*795d594fSAndroid Build Coastguard Worker   // The end address of the memory region that's managed by this allocator.
End()775*795d594fSAndroid Build Coastguard Worker   uint8_t* End() { return base_ + capacity_; }
776*795d594fSAndroid Build Coastguard Worker 
777*795d594fSAndroid Build Coastguard Worker   // Page-granularity alloc/free
778*795d594fSAndroid Build Coastguard Worker   void* AllocPages(Thread* self, size_t num_pages, uint8_t page_map_type)
779*795d594fSAndroid Build Coastguard Worker       REQUIRES(lock_);
780*795d594fSAndroid Build Coastguard Worker   // Returns how many bytes were freed.
781*795d594fSAndroid Build Coastguard Worker   size_t FreePages(Thread* self, void* ptr, bool already_zero) REQUIRES(lock_);
782*795d594fSAndroid Build Coastguard Worker 
783*795d594fSAndroid Build Coastguard Worker   // Allocate/free a run slot.
784*795d594fSAndroid Build Coastguard Worker   EXPORT void* AllocFromRun(Thread* self,
785*795d594fSAndroid Build Coastguard Worker                             size_t size,
786*795d594fSAndroid Build Coastguard Worker                             size_t* bytes_allocated,
787*795d594fSAndroid Build Coastguard Worker                             size_t* usable_size,
788*795d594fSAndroid Build Coastguard Worker                             size_t* bytes_tl_bulk_allocated) REQUIRES(!lock_);
789*795d594fSAndroid Build Coastguard Worker   // Allocate/free a run slot without acquiring locks.
790*795d594fSAndroid Build Coastguard Worker   // TODO: REQUIRES(Locks::mutator_lock_)
791*795d594fSAndroid Build Coastguard Worker   void* AllocFromRunThreadUnsafe(Thread* self, size_t size, size_t* bytes_allocated,
792*795d594fSAndroid Build Coastguard Worker                                  size_t* usable_size, size_t* bytes_tl_bulk_allocated)
793*795d594fSAndroid Build Coastguard Worker       REQUIRES(!lock_);
794*795d594fSAndroid Build Coastguard Worker   void* AllocFromCurrentRunUnlocked(Thread* self, size_t idx) REQUIRES(!lock_);
795*795d594fSAndroid Build Coastguard Worker 
796*795d594fSAndroid Build Coastguard Worker   // Returns the bracket size.
797*795d594fSAndroid Build Coastguard Worker   size_t FreeFromRun(Thread* self, void* ptr, Run* run)
798*795d594fSAndroid Build Coastguard Worker       REQUIRES(!lock_);
799*795d594fSAndroid Build Coastguard Worker 
800*795d594fSAndroid Build Coastguard Worker   // Used to allocate a new thread local run for a size bracket.
801*795d594fSAndroid Build Coastguard Worker   Run* AllocRun(Thread* self, size_t idx) REQUIRES(!lock_);
802*795d594fSAndroid Build Coastguard Worker 
803*795d594fSAndroid Build Coastguard Worker   // Used to acquire a new/reused run for a size bracket. Used when a
804*795d594fSAndroid Build Coastguard Worker   // thread-local or current run gets full.
805*795d594fSAndroid Build Coastguard Worker   Run* RefillRun(Thread* self, size_t idx) REQUIRES(!lock_);
806*795d594fSAndroid Build Coastguard Worker 
807*795d594fSAndroid Build Coastguard Worker   // The internal of non-bulk Free().
808*795d594fSAndroid Build Coastguard Worker   size_t FreeInternal(Thread* self, void* ptr) REQUIRES(!lock_);
809*795d594fSAndroid Build Coastguard Worker 
810*795d594fSAndroid Build Coastguard Worker   // Allocates large objects.
811*795d594fSAndroid Build Coastguard Worker   EXPORT void* AllocLargeObject(Thread* self,
812*795d594fSAndroid Build Coastguard Worker                                 size_t size,
813*795d594fSAndroid Build Coastguard Worker                                 size_t* bytes_allocated,
814*795d594fSAndroid Build Coastguard Worker                                 size_t* usable_size,
815*795d594fSAndroid Build Coastguard Worker                                 size_t* bytes_tl_bulk_allocated) REQUIRES(!lock_);
816*795d594fSAndroid Build Coastguard Worker 
817*795d594fSAndroid Build Coastguard Worker   // Revoke a run by adding it to non_full_runs_ or freeing the pages.
818*795d594fSAndroid Build Coastguard Worker   void RevokeRun(Thread* self, size_t idx, Run* run) REQUIRES(!lock_);
819*795d594fSAndroid Build Coastguard Worker 
820*795d594fSAndroid Build Coastguard Worker   // Revoke the current runs which share an index with the thread local runs.
821*795d594fSAndroid Build Coastguard Worker   void RevokeThreadUnsafeCurrentRuns() REQUIRES(!lock_);
822*795d594fSAndroid Build Coastguard Worker 
823*795d594fSAndroid Build Coastguard Worker   // Release a range of pages.
824*795d594fSAndroid Build Coastguard Worker   size_t ReleasePageRange(uint8_t* start, uint8_t* end) REQUIRES(lock_);
825*795d594fSAndroid Build Coastguard Worker 
826*795d594fSAndroid Build Coastguard Worker   // Dumps the page map for debugging.
827*795d594fSAndroid Build Coastguard Worker   std::string DumpPageMap() REQUIRES(lock_);
828*795d594fSAndroid Build Coastguard Worker 
829*795d594fSAndroid Build Coastguard Worker  public:
830*795d594fSAndroid Build Coastguard Worker   RosAlloc(void* base, size_t capacity, size_t max_capacity,
831*795d594fSAndroid Build Coastguard Worker            PageReleaseMode page_release_mode,
832*795d594fSAndroid Build Coastguard Worker            bool running_on_memory_tool,
833*795d594fSAndroid Build Coastguard Worker            size_t page_release_size_threshold = kDefaultPageReleaseSizeThreshold);
834*795d594fSAndroid Build Coastguard Worker   ~RosAlloc();
835*795d594fSAndroid Build Coastguard Worker 
RunFreeListOffset()836*795d594fSAndroid Build Coastguard Worker   static constexpr size_t RunFreeListOffset() {
837*795d594fSAndroid Build Coastguard Worker     return OFFSETOF_MEMBER(Run, free_list_);
838*795d594fSAndroid Build Coastguard Worker   }
RunFreeListHeadOffset()839*795d594fSAndroid Build Coastguard Worker   static constexpr size_t RunFreeListHeadOffset() {
840*795d594fSAndroid Build Coastguard Worker     return OFFSETOF_MEMBER(SlotFreeList<false>, head_);
841*795d594fSAndroid Build Coastguard Worker   }
RunFreeListSizeOffset()842*795d594fSAndroid Build Coastguard Worker   static constexpr size_t RunFreeListSizeOffset() {
843*795d594fSAndroid Build Coastguard Worker     return OFFSETOF_MEMBER(SlotFreeList<false>, size_);
844*795d594fSAndroid Build Coastguard Worker   }
RunSlotNextOffset()845*795d594fSAndroid Build Coastguard Worker   static constexpr size_t RunSlotNextOffset() {
846*795d594fSAndroid Build Coastguard Worker     return OFFSETOF_MEMBER(Slot, next_);
847*795d594fSAndroid Build Coastguard Worker   }
848*795d594fSAndroid Build Coastguard Worker 
849*795d594fSAndroid Build Coastguard Worker   // If kThreadUnsafe is true then the allocator may avoid acquiring some locks as an optimization.
850*795d594fSAndroid Build Coastguard Worker   // If used, this may cause race conditions if multiple threads are allocating at the same time.
851*795d594fSAndroid Build Coastguard Worker   template<bool kThreadSafe = true>
852*795d594fSAndroid Build Coastguard Worker   void* Alloc(Thread* self, size_t size, size_t* bytes_allocated, size_t* usable_size,
853*795d594fSAndroid Build Coastguard Worker               size_t* bytes_tl_bulk_allocated)
854*795d594fSAndroid Build Coastguard Worker       REQUIRES(!lock_);
855*795d594fSAndroid Build Coastguard Worker   size_t Free(Thread* self, void* ptr)
856*795d594fSAndroid Build Coastguard Worker       REQUIRES(!bulk_free_lock_, !lock_);
857*795d594fSAndroid Build Coastguard Worker   size_t BulkFree(Thread* self, void** ptrs, size_t num_ptrs)
858*795d594fSAndroid Build Coastguard Worker       REQUIRES(!bulk_free_lock_, !lock_);
859*795d594fSAndroid Build Coastguard Worker 
860*795d594fSAndroid Build Coastguard Worker   // Returns true if the given allocation request can be allocated in
861*795d594fSAndroid Build Coastguard Worker   // an existing thread local run without allocating a new run.
862*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool CanAllocFromThreadLocalRun(Thread* self, size_t size);
863*795d594fSAndroid Build Coastguard Worker   // Allocate the given allocation request in an existing thread local
864*795d594fSAndroid Build Coastguard Worker   // run without allocating a new run.
865*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE void* AllocFromThreadLocalRun(Thread* self, size_t size, size_t* bytes_allocated);
866*795d594fSAndroid Build Coastguard Worker 
867*795d594fSAndroid Build Coastguard Worker   // Returns the maximum bytes that could be allocated for the given
868*795d594fSAndroid Build Coastguard Worker   // size in bulk, that is the maximum value for the
869*795d594fSAndroid Build Coastguard Worker   // bytes_allocated_bulk out param returned by RosAlloc::Alloc().
870*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE size_t MaxBytesBulkAllocatedFor(size_t size);
871*795d594fSAndroid Build Coastguard Worker 
872*795d594fSAndroid Build Coastguard Worker   // Returns the size of the allocated slot for a given allocated memory chunk.
873*795d594fSAndroid Build Coastguard Worker   size_t UsableSize(const void* ptr) REQUIRES(!lock_);
874*795d594fSAndroid Build Coastguard Worker   // Returns the size of the allocated slot for a given size.
UsableSize(size_t bytes)875*795d594fSAndroid Build Coastguard Worker   size_t UsableSize(size_t bytes) {
876*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(bytes > kLargeSizeThreshold)) {
877*795d594fSAndroid Build Coastguard Worker       return RoundUp(bytes, gPageSize);
878*795d594fSAndroid Build Coastguard Worker     } else {
879*795d594fSAndroid Build Coastguard Worker       return RoundToBracketSize(bytes);
880*795d594fSAndroid Build Coastguard Worker     }
881*795d594fSAndroid Build Coastguard Worker   }
882*795d594fSAndroid Build Coastguard Worker   // Try to reduce the current footprint by releasing the free page
883*795d594fSAndroid Build Coastguard Worker   // run at the end of the memory region, if any.
884*795d594fSAndroid Build Coastguard Worker   bool Trim() REQUIRES(!lock_);
885*795d594fSAndroid Build Coastguard Worker   // Iterates over all the memory slots and apply the given function.
886*795d594fSAndroid Build Coastguard Worker   void InspectAll(void (*handler)(void* start, void* end, size_t used_bytes, void* callback_arg),
887*795d594fSAndroid Build Coastguard Worker                   void* arg)
888*795d594fSAndroid Build Coastguard Worker       REQUIRES(!lock_);
889*795d594fSAndroid Build Coastguard Worker 
890*795d594fSAndroid Build Coastguard Worker   // Release empty pages.
891*795d594fSAndroid Build Coastguard Worker   size_t ReleasePages() REQUIRES(!lock_);
892*795d594fSAndroid Build Coastguard Worker   // Returns the current footprint.
893*795d594fSAndroid Build Coastguard Worker   size_t Footprint() REQUIRES(!lock_);
894*795d594fSAndroid Build Coastguard Worker   // Returns the current capacity, maximum footprint.
895*795d594fSAndroid Build Coastguard Worker   size_t FootprintLimit() REQUIRES(!lock_);
896*795d594fSAndroid Build Coastguard Worker   // Update the current capacity.
897*795d594fSAndroid Build Coastguard Worker   void SetFootprintLimit(size_t bytes) REQUIRES(!lock_);
898*795d594fSAndroid Build Coastguard Worker 
899*795d594fSAndroid Build Coastguard Worker   // Releases the thread-local runs assigned to the given thread back to the common set of runs.
900*795d594fSAndroid Build Coastguard Worker   // Returns the total bytes of free slots in the revoked thread local runs. This is to be
901*795d594fSAndroid Build Coastguard Worker   // subtracted from Heap::num_bytes_allocated_ to cancel out the ahead-of-time counting.
902*795d594fSAndroid Build Coastguard Worker   size_t RevokeThreadLocalRuns(Thread* thread) REQUIRES(!lock_, !bulk_free_lock_);
903*795d594fSAndroid Build Coastguard Worker   // Releases the thread-local runs assigned to all the threads back to the common set of runs.
904*795d594fSAndroid Build Coastguard Worker   // Returns the total bytes of free slots in the revoked thread local runs. This is to be
905*795d594fSAndroid Build Coastguard Worker   // subtracted from Heap::num_bytes_allocated_ to cancel out the ahead-of-time counting.
906*795d594fSAndroid Build Coastguard Worker   size_t RevokeAllThreadLocalRuns() REQUIRES(!Locks::thread_list_lock_, !lock_, !bulk_free_lock_);
907*795d594fSAndroid Build Coastguard Worker   // Assert the thread local runs of a thread are revoked.
908*795d594fSAndroid Build Coastguard Worker   void AssertThreadLocalRunsAreRevoked(Thread* thread) REQUIRES(!bulk_free_lock_);
909*795d594fSAndroid Build Coastguard Worker   // Assert all the thread local runs are revoked.
910*795d594fSAndroid Build Coastguard Worker   void AssertAllThreadLocalRunsAreRevoked() REQUIRES(!Locks::thread_list_lock_, !bulk_free_lock_);
911*795d594fSAndroid Build Coastguard Worker 
GetDedicatedFullRun()912*795d594fSAndroid Build Coastguard Worker   static Run* GetDedicatedFullRun() {
913*795d594fSAndroid Build Coastguard Worker     return dedicated_full_run_;
914*795d594fSAndroid Build Coastguard Worker   }
IsFreePage(size_t idx)915*795d594fSAndroid Build Coastguard Worker   bool IsFreePage(size_t idx) const {
916*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(idx, DivideByPageSize(capacity_));
917*795d594fSAndroid Build Coastguard Worker     uint8_t pm_type = page_map_[idx];
918*795d594fSAndroid Build Coastguard Worker     return pm_type == kPageMapReleased || pm_type == kPageMapEmpty;
919*795d594fSAndroid Build Coastguard Worker   }
920*795d594fSAndroid Build Coastguard Worker 
921*795d594fSAndroid Build Coastguard Worker   // Callbacks for InspectAll that will count the number of bytes
922*795d594fSAndroid Build Coastguard Worker   // allocated and objects allocated, respectively.
923*795d594fSAndroid Build Coastguard Worker   static void BytesAllocatedCallback(void* start, void* end, size_t used_bytes, void* arg);
924*795d594fSAndroid Build Coastguard Worker   static void ObjectsAllocatedCallback(void* start, void* end, size_t used_bytes, void* arg);
925*795d594fSAndroid Build Coastguard Worker 
DoesReleaseAllPages()926*795d594fSAndroid Build Coastguard Worker   bool DoesReleaseAllPages() const {
927*795d594fSAndroid Build Coastguard Worker     return page_release_mode_ == kPageReleaseModeAll;
928*795d594fSAndroid Build Coastguard Worker   }
929*795d594fSAndroid Build Coastguard Worker 
930*795d594fSAndroid Build Coastguard Worker   // Verify for debugging.
931*795d594fSAndroid Build Coastguard Worker   void Verify() REQUIRES(Locks::mutator_lock_, !Locks::thread_list_lock_, !bulk_free_lock_,
932*795d594fSAndroid Build Coastguard Worker                          !lock_);
933*795d594fSAndroid Build Coastguard Worker 
934*795d594fSAndroid Build Coastguard Worker   bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes)
935*795d594fSAndroid Build Coastguard Worker       REQUIRES(!bulk_free_lock_, !lock_);
936*795d594fSAndroid Build Coastguard Worker 
937*795d594fSAndroid Build Coastguard Worker   void DumpStats(std::ostream& os)
938*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::mutator_lock_) REQUIRES(!lock_) REQUIRES(!bulk_free_lock_);
939*795d594fSAndroid Build Coastguard Worker 
940*795d594fSAndroid Build Coastguard Worker  private:
941*795d594fSAndroid Build Coastguard Worker   friend std::ostream& operator<<(std::ostream& os, RosAlloc::PageMapKind rhs);
942*795d594fSAndroid Build Coastguard Worker 
943*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(RosAlloc);
944*795d594fSAndroid Build Coastguard Worker };
945*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, RosAlloc::PageMapKind rhs);
946*795d594fSAndroid Build Coastguard Worker 
947*795d594fSAndroid Build Coastguard Worker // Callback from rosalloc when it needs to increase the footprint. Must be implemented somewhere
948*795d594fSAndroid Build Coastguard Worker // else (currently rosalloc_space.cc).
949*795d594fSAndroid Build Coastguard Worker void* ArtRosAllocMoreCore(allocator::RosAlloc* rosalloc, intptr_t increment);
950*795d594fSAndroid Build Coastguard Worker 
951*795d594fSAndroid Build Coastguard Worker }  // namespace allocator
952*795d594fSAndroid Build Coastguard Worker }  // namespace gc
953*795d594fSAndroid Build Coastguard Worker }  // namespace art
954*795d594fSAndroid Build Coastguard Worker 
955*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_GC_ALLOCATOR_ROSALLOC_H_
956