1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 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_LINEAR_ALLOC_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_LINEAR_ALLOC_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "base/arena_allocator.h" 21*795d594fSAndroid Build Coastguard Worker #include "base/casts.h" 22*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 23*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h" 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Worker class ArenaPool; 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker enum class LinearAllocKind : uint32_t { 30*795d594fSAndroid Build Coastguard Worker kNoGCRoots = 0, // No GC-root kind should always be 0. 31*795d594fSAndroid Build Coastguard Worker kGCRootArray, 32*795d594fSAndroid Build Coastguard Worker kArtMethodArray, 33*795d594fSAndroid Build Coastguard Worker kArtFieldArray, 34*795d594fSAndroid Build Coastguard Worker kDexCacheArray, 35*795d594fSAndroid Build Coastguard Worker kArtMethod 36*795d594fSAndroid Build Coastguard Worker }; 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker // Header for every allocation in LinearAlloc. The header provides the type 39*795d594fSAndroid Build Coastguard Worker // and size information to the GC for invoking the right visitor. 40*795d594fSAndroid Build Coastguard Worker class TrackingHeader final { 41*795d594fSAndroid Build Coastguard Worker public: 42*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kIs16Aligned = 1; 43*795d594fSAndroid Build Coastguard Worker TrackingHeader(size_t size, LinearAllocKind kind, bool is_16_aligned = false) kind_(kind)44*795d594fSAndroid Build Coastguard Worker : kind_(kind), size_(dchecked_integral_cast<uint32_t>(size)) { 45*795d594fSAndroid Build Coastguard Worker // We need the last bit to store 16-byte alignment flag. 46*795d594fSAndroid Build Coastguard Worker CHECK_EQ(size_ & kIs16Aligned, 0u); 47*795d594fSAndroid Build Coastguard Worker if (is_16_aligned) { 48*795d594fSAndroid Build Coastguard Worker size_ |= kIs16Aligned; 49*795d594fSAndroid Build Coastguard Worker } 50*795d594fSAndroid Build Coastguard Worker } 51*795d594fSAndroid Build Coastguard Worker GetKind()52*795d594fSAndroid Build Coastguard Worker LinearAllocKind GetKind() const { return kind_; } 53*795d594fSAndroid Build Coastguard Worker // Since we are linearly allocating and hop from one object to the next during 54*795d594fSAndroid Build Coastguard Worker // visits, reading 'size_ == 0' indicates that there are no more objects to 55*795d594fSAndroid Build Coastguard Worker // visit in the given page. But ASAN detects it as use-after-poison access. GetSize()56*795d594fSAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_ADDRESS size_t GetSize() const { return size_ & ~kIs16Aligned; } Is16Aligned()57*795d594fSAndroid Build Coastguard Worker bool Is16Aligned() const { return size_ & kIs16Aligned; } 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker private: SetKind(LinearAllocKind kind)60*795d594fSAndroid Build Coastguard Worker void SetKind(LinearAllocKind kind) { kind_ = kind; } 61*795d594fSAndroid Build Coastguard Worker 62*795d594fSAndroid Build Coastguard Worker LinearAllocKind kind_; 63*795d594fSAndroid Build Coastguard Worker uint32_t size_; 64*795d594fSAndroid Build Coastguard Worker 65*795d594fSAndroid Build Coastguard Worker friend class LinearAlloc; // For SetKind() 66*795d594fSAndroid Build Coastguard Worker 67*795d594fSAndroid Build Coastguard Worker DISALLOW_IMPLICIT_CONSTRUCTORS(TrackingHeader); 68*795d594fSAndroid Build Coastguard Worker }; 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, LinearAllocKind value); 71*795d594fSAndroid Build Coastguard Worker 72*795d594fSAndroid Build Coastguard Worker class LinearAlloc { 73*795d594fSAndroid Build Coastguard Worker public: 74*795d594fSAndroid Build Coastguard Worker static constexpr size_t kAlignment = 8u; 75*795d594fSAndroid Build Coastguard Worker static_assert(kAlignment >= ArenaAllocator::kAlignment); 76*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(TrackingHeader) == ArenaAllocator::kAlignment); 77*795d594fSAndroid Build Coastguard Worker LinearAlloc(ArenaPool * pool,bool track_allocs)78*795d594fSAndroid Build Coastguard Worker explicit LinearAlloc(ArenaPool* pool, bool track_allocs) 79*795d594fSAndroid Build Coastguard Worker : lock_("linear alloc"), allocator_(pool), track_allocations_(track_allocs) {} 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker void* Alloc(Thread* self, size_t size, LinearAllocKind kind) REQUIRES(!lock_); 82*795d594fSAndroid Build Coastguard Worker void* AllocAlign16(Thread* self, size_t size, LinearAllocKind kind) REQUIRES(!lock_); 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker // Realloc never frees the input pointer, it is the caller's job to do this if necessary. 85*795d594fSAndroid Build Coastguard Worker void* Realloc(Thread* self, void* ptr, size_t old_size, size_t new_size, LinearAllocKind kind) 86*795d594fSAndroid Build Coastguard Worker REQUIRES(!lock_); 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker // Allocate an array of structs of type T. 89*795d594fSAndroid Build Coastguard Worker template<class T> AllocArray(Thread * self,size_t elements,LinearAllocKind kind)90*795d594fSAndroid Build Coastguard Worker T* AllocArray(Thread* self, size_t elements, LinearAllocKind kind) REQUIRES(!lock_) { 91*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<T*>(Alloc(self, elements * sizeof(T), kind)); 92*795d594fSAndroid Build Coastguard Worker } 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker // Return the number of bytes used in the allocator. 95*795d594fSAndroid Build Coastguard Worker size_t GetUsedMemory() const REQUIRES(!lock_); 96*795d594fSAndroid Build Coastguard Worker 97*795d594fSAndroid Build Coastguard Worker ArenaPool* GetArenaPool() REQUIRES(!lock_); 98*795d594fSAndroid Build Coastguard Worker // Force arena allocator to ask for a new arena on next allocation. This 99*795d594fSAndroid Build Coastguard Worker // is to preserve private/shared clean pages across zygote fork. 100*795d594fSAndroid Build Coastguard Worker void SetupForPostZygoteFork(Thread* self) REQUIRES(!lock_); 101*795d594fSAndroid Build Coastguard Worker // Convert the given allocated object into a `no GC-root` so that compaction 102*795d594fSAndroid Build Coastguard Worker // skips it. Currently only used during class linking for ArtMethod array. 103*795d594fSAndroid Build Coastguard Worker void ConvertToNoGcRoots(void* ptr, LinearAllocKind orig_kind); 104*795d594fSAndroid Build Coastguard Worker 105*795d594fSAndroid Build Coastguard Worker // Return true if the linear alloc contains an address. 106*795d594fSAndroid Build Coastguard Worker bool Contains(void* ptr) const REQUIRES(!lock_); 107*795d594fSAndroid Build Coastguard Worker 108*795d594fSAndroid Build Coastguard Worker // Unsafe version of 'Contains' only to be used when the allocator is going 109*795d594fSAndroid Build Coastguard Worker // to be deleted. ContainsUnsafe(void * ptr)110*795d594fSAndroid Build Coastguard Worker bool ContainsUnsafe(void* ptr) const NO_THREAD_SAFETY_ANALYSIS { 111*795d594fSAndroid Build Coastguard Worker return allocator_.Contains(ptr); 112*795d594fSAndroid Build Coastguard Worker } 113*795d594fSAndroid Build Coastguard Worker 114*795d594fSAndroid Build Coastguard Worker // Set the given object as the first object for all the pages where the 115*795d594fSAndroid Build Coastguard Worker // page-beginning overlaps with the object. 116*795d594fSAndroid Build Coastguard Worker void SetFirstObject(void* begin, size_t bytes) const REQUIRES(lock_); 117*795d594fSAndroid Build Coastguard Worker 118*795d594fSAndroid Build Coastguard Worker private: 119*795d594fSAndroid Build Coastguard Worker mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 120*795d594fSAndroid Build Coastguard Worker ArenaAllocator allocator_ GUARDED_BY(lock_); 121*795d594fSAndroid Build Coastguard Worker const bool track_allocations_; 122*795d594fSAndroid Build Coastguard Worker 123*795d594fSAndroid Build Coastguard Worker DISALLOW_IMPLICIT_CONSTRUCTORS(LinearAlloc); 124*795d594fSAndroid Build Coastguard Worker }; 125*795d594fSAndroid Build Coastguard Worker 126*795d594fSAndroid Build Coastguard Worker } // namespace art 127*795d594fSAndroid Build Coastguard Worker 128*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_LINEAR_ALLOC_H_ 129