xref: /aosp_15_r20/art/runtime/linear_alloc.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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