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