1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_LINEAR_ALLOC_H_ 18 #define ART_RUNTIME_LINEAR_ALLOC_H_ 19 20 #include "base/arena_allocator.h" 21 #include "base/casts.h" 22 #include "base/mutex.h" 23 24 namespace art { 25 26 class ArenaPool; 27 28 enum class LinearAllocKind : uint32_t { 29 kNoGCRoots = 0, // No GC-root kind should always be 0. 30 kGCRootArray, 31 kArtMethodArray, 32 kArtFieldArray, 33 kDexCacheArray, 34 kArtMethod 35 }; 36 37 // Header for every allocation in LinearAlloc. The header provides the type 38 // and size information to the GC for invoking the right visitor. 39 class TrackingHeader final { 40 public: 41 static constexpr uint32_t kIs16Aligned = 1; 42 TrackingHeader(size_t size, LinearAllocKind kind, bool is_16_aligned = false) kind_(kind)43 : kind_(kind), size_(dchecked_integral_cast<uint32_t>(size)) { 44 // We need the last bit to store 16-byte alignment flag. 45 CHECK_EQ(size_ & kIs16Aligned, 0u); 46 if (is_16_aligned) { 47 size_ |= kIs16Aligned; 48 } 49 } 50 GetKind()51 LinearAllocKind GetKind() const { return kind_; } 52 // Since we are linearly allocating and hop from one object to the next during 53 // visits, reading 'size_ == 0' indicates that there are no more objects to 54 // visit in the given page. But ASAN detects it as use-after-poison access. GetSize()55 ATTRIBUTE_NO_SANITIZE_ADDRESS size_t GetSize() const { return size_ & ~kIs16Aligned; } Is16Aligned()56 bool Is16Aligned() const { return size_ & kIs16Aligned; } 57 58 private: 59 LinearAllocKind kind_; 60 uint32_t size_; 61 62 DISALLOW_IMPLICIT_CONSTRUCTORS(TrackingHeader); 63 }; 64 65 std::ostream& operator<<(std::ostream& os, LinearAllocKind value); 66 67 class LinearAlloc { 68 public: 69 static constexpr size_t kAlignment = 8u; 70 static_assert(kAlignment >= ArenaAllocator::kAlignment); 71 static_assert(sizeof(TrackingHeader) == ArenaAllocator::kAlignment); 72 LinearAlloc(ArenaPool * pool,bool track_allocs)73 explicit LinearAlloc(ArenaPool* pool, bool track_allocs) 74 : lock_("linear alloc"), allocator_(pool), track_allocations_(track_allocs) {} 75 76 void* Alloc(Thread* self, size_t size, LinearAllocKind kind) REQUIRES(!lock_); 77 void* AllocAlign16(Thread* self, size_t size, LinearAllocKind kind) REQUIRES(!lock_); 78 79 // Realloc never frees the input pointer, it is the caller's job to do this if necessary. 80 void* Realloc(Thread* self, void* ptr, size_t old_size, size_t new_size, LinearAllocKind kind) 81 REQUIRES(!lock_); 82 83 // Allocate an array of structs of type T. 84 template<class T> AllocArray(Thread * self,size_t elements,LinearAllocKind kind)85 T* AllocArray(Thread* self, size_t elements, LinearAllocKind kind) REQUIRES(!lock_) { 86 return reinterpret_cast<T*>(Alloc(self, elements * sizeof(T), kind)); 87 } 88 89 // Return the number of bytes used in the allocator. 90 size_t GetUsedMemory() const REQUIRES(!lock_); 91 92 ArenaPool* GetArenaPool() REQUIRES(!lock_); 93 // Force arena allocator to ask for a new arena on next allocation. This 94 // is to preserve private/shared clean pages across zygote fork. 95 void SetupForPostZygoteFork(Thread* self) REQUIRES(!lock_); 96 97 // Return true if the linear alloc contains an address. 98 bool Contains(void* ptr) const REQUIRES(!lock_); 99 100 // Unsafe version of 'Contains' only to be used when the allocator is going 101 // to be deleted. ContainsUnsafe(void * ptr)102 bool ContainsUnsafe(void* ptr) const NO_THREAD_SAFETY_ANALYSIS { 103 return allocator_.Contains(ptr); 104 } 105 106 // Set the given object as the first object for all the pages where the 107 // page-beginning overlaps with the object. 108 void SetFirstObject(void* begin, size_t bytes) const REQUIRES(lock_); 109 110 private: 111 mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 112 ArenaAllocator allocator_ GUARDED_BY(lock_); 113 const bool track_allocations_; 114 115 DISALLOW_IMPLICIT_CONSTRUCTORS(LinearAlloc); 116 }; 117 118 } // namespace art 119 120 #endif // ART_RUNTIME_LINEAR_ALLOC_H_ 121