xref: /aosp_15_r20/art/runtime/gc/space/rosalloc_space.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker 
2*795d594fSAndroid Build Coastguard Worker /*
3*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
4*795d594fSAndroid Build Coastguard Worker  *
5*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
8*795d594fSAndroid Build Coastguard Worker  *
9*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
10*795d594fSAndroid Build Coastguard Worker  *
11*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
16*795d594fSAndroid Build Coastguard Worker  */
17*795d594fSAndroid Build Coastguard Worker 
18*795d594fSAndroid Build Coastguard Worker #include "rosalloc_space-inl.h"
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/logging.h"  // For VLOG.
21*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
23*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/card_table.h"
24*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/space_bitmap-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
26*795d594fSAndroid Build Coastguard Worker #include "memory_tool_malloc_space-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
30*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "thread.h"
32*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
35*795d594fSAndroid Build Coastguard Worker namespace gc {
36*795d594fSAndroid Build Coastguard Worker namespace space {
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker static constexpr bool kPrefetchDuringRosAllocFreeList = false;
39*795d594fSAndroid Build Coastguard Worker static constexpr size_t kPrefetchLookAhead = 8;
40*795d594fSAndroid Build Coastguard Worker // Use this only for verification, it is not safe to use since the class of the object may have
41*795d594fSAndroid Build Coastguard Worker // been freed.
42*795d594fSAndroid Build Coastguard Worker static constexpr bool kVerifyFreedBytes = false;
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker // TODO: Fix
45*795d594fSAndroid Build Coastguard Worker // template class MemoryToolMallocSpace<RosAllocSpace, allocator::RosAlloc*>;
46*795d594fSAndroid Build Coastguard Worker 
RosAllocSpace(MemMap && mem_map,size_t initial_size,const std::string & name,art::gc::allocator::RosAlloc * rosalloc,uint8_t * begin,uint8_t * end,uint8_t * limit,size_t growth_limit,bool can_move_objects,size_t starting_size,bool low_memory_mode)47*795d594fSAndroid Build Coastguard Worker RosAllocSpace::RosAllocSpace(MemMap&& mem_map,
48*795d594fSAndroid Build Coastguard Worker                              size_t initial_size,
49*795d594fSAndroid Build Coastguard Worker                              const std::string& name,
50*795d594fSAndroid Build Coastguard Worker                              art::gc::allocator::RosAlloc* rosalloc,
51*795d594fSAndroid Build Coastguard Worker                              uint8_t* begin,
52*795d594fSAndroid Build Coastguard Worker                              uint8_t* end,
53*795d594fSAndroid Build Coastguard Worker                              uint8_t* limit,
54*795d594fSAndroid Build Coastguard Worker                              size_t growth_limit,
55*795d594fSAndroid Build Coastguard Worker                              bool can_move_objects,
56*795d594fSAndroid Build Coastguard Worker                              size_t starting_size,
57*795d594fSAndroid Build Coastguard Worker                              bool low_memory_mode)
58*795d594fSAndroid Build Coastguard Worker     : MallocSpace(name,
59*795d594fSAndroid Build Coastguard Worker                   std::move(mem_map),
60*795d594fSAndroid Build Coastguard Worker                   begin,
61*795d594fSAndroid Build Coastguard Worker                   end,
62*795d594fSAndroid Build Coastguard Worker                   limit,
63*795d594fSAndroid Build Coastguard Worker                   growth_limit,
64*795d594fSAndroid Build Coastguard Worker                   true,
65*795d594fSAndroid Build Coastguard Worker                   can_move_objects,
66*795d594fSAndroid Build Coastguard Worker                   starting_size, initial_size),
67*795d594fSAndroid Build Coastguard Worker       rosalloc_(rosalloc), low_memory_mode_(low_memory_mode) {
68*795d594fSAndroid Build Coastguard Worker   CHECK(rosalloc != nullptr);
69*795d594fSAndroid Build Coastguard Worker }
70*795d594fSAndroid Build Coastguard Worker 
CreateFromMemMap(MemMap && mem_map,const std::string & name,size_t starting_size,size_t initial_size,size_t growth_limit,size_t capacity,bool low_memory_mode,bool can_move_objects)71*795d594fSAndroid Build Coastguard Worker RosAllocSpace* RosAllocSpace::CreateFromMemMap(MemMap&& mem_map,
72*795d594fSAndroid Build Coastguard Worker                                                const std::string& name,
73*795d594fSAndroid Build Coastguard Worker                                                size_t starting_size,
74*795d594fSAndroid Build Coastguard Worker                                                size_t initial_size,
75*795d594fSAndroid Build Coastguard Worker                                                size_t growth_limit,
76*795d594fSAndroid Build Coastguard Worker                                                size_t capacity,
77*795d594fSAndroid Build Coastguard Worker                                                bool low_memory_mode,
78*795d594fSAndroid Build Coastguard Worker                                                bool can_move_objects) {
79*795d594fSAndroid Build Coastguard Worker   DCHECK(mem_map.IsValid());
80*795d594fSAndroid Build Coastguard Worker 
81*795d594fSAndroid Build Coastguard Worker   bool running_on_memory_tool = Runtime::Current()->IsRunningOnMemoryTool();
82*795d594fSAndroid Build Coastguard Worker 
83*795d594fSAndroid Build Coastguard Worker   allocator::RosAlloc* rosalloc = CreateRosAlloc(mem_map.Begin(),
84*795d594fSAndroid Build Coastguard Worker                                                  starting_size,
85*795d594fSAndroid Build Coastguard Worker                                                  initial_size,
86*795d594fSAndroid Build Coastguard Worker                                                  capacity,
87*795d594fSAndroid Build Coastguard Worker                                                  low_memory_mode,
88*795d594fSAndroid Build Coastguard Worker                                                  running_on_memory_tool);
89*795d594fSAndroid Build Coastguard Worker   if (rosalloc == nullptr) {
90*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to initialize rosalloc for alloc space (" << name << ")";
91*795d594fSAndroid Build Coastguard Worker     return nullptr;
92*795d594fSAndroid Build Coastguard Worker   }
93*795d594fSAndroid Build Coastguard Worker 
94*795d594fSAndroid Build Coastguard Worker   // Protect memory beyond the starting size. MoreCore will add r/w permissions when necessory
95*795d594fSAndroid Build Coastguard Worker   uint8_t* end = mem_map.Begin() + starting_size;
96*795d594fSAndroid Build Coastguard Worker   if (capacity - starting_size > 0) {
97*795d594fSAndroid Build Coastguard Worker     CheckedCall(mprotect, name.c_str(), end, capacity - starting_size, PROT_NONE);
98*795d594fSAndroid Build Coastguard Worker   }
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   // Everything is set so record in immutable structure and leave
101*795d594fSAndroid Build Coastguard Worker   uint8_t* begin = mem_map.Begin();
102*795d594fSAndroid Build Coastguard Worker   // TODO: Fix RosAllocSpace to support ASan. There is currently some issues with
103*795d594fSAndroid Build Coastguard Worker   // AllocationSize caused by redzones. b/12944686
104*795d594fSAndroid Build Coastguard Worker   if (running_on_memory_tool) {
105*795d594fSAndroid Build Coastguard Worker     return new MemoryToolMallocSpace<RosAllocSpace, kDefaultMemoryToolRedZoneBytes, false, true>(
106*795d594fSAndroid Build Coastguard Worker         std::move(mem_map),
107*795d594fSAndroid Build Coastguard Worker         initial_size,
108*795d594fSAndroid Build Coastguard Worker         name,
109*795d594fSAndroid Build Coastguard Worker         rosalloc,
110*795d594fSAndroid Build Coastguard Worker         begin,
111*795d594fSAndroid Build Coastguard Worker         end,
112*795d594fSAndroid Build Coastguard Worker         begin + capacity,
113*795d594fSAndroid Build Coastguard Worker         growth_limit,
114*795d594fSAndroid Build Coastguard Worker         can_move_objects,
115*795d594fSAndroid Build Coastguard Worker         starting_size,
116*795d594fSAndroid Build Coastguard Worker         low_memory_mode);
117*795d594fSAndroid Build Coastguard Worker   } else {
118*795d594fSAndroid Build Coastguard Worker     return new RosAllocSpace(std::move(mem_map),
119*795d594fSAndroid Build Coastguard Worker                              initial_size,
120*795d594fSAndroid Build Coastguard Worker                              name,
121*795d594fSAndroid Build Coastguard Worker                              rosalloc,
122*795d594fSAndroid Build Coastguard Worker                              begin,
123*795d594fSAndroid Build Coastguard Worker                              end,
124*795d594fSAndroid Build Coastguard Worker                              begin + capacity,
125*795d594fSAndroid Build Coastguard Worker                              growth_limit,
126*795d594fSAndroid Build Coastguard Worker                              can_move_objects,
127*795d594fSAndroid Build Coastguard Worker                              starting_size,
128*795d594fSAndroid Build Coastguard Worker                              low_memory_mode);
129*795d594fSAndroid Build Coastguard Worker   }
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker 
~RosAllocSpace()132*795d594fSAndroid Build Coastguard Worker RosAllocSpace::~RosAllocSpace() {
133*795d594fSAndroid Build Coastguard Worker   delete rosalloc_;
134*795d594fSAndroid Build Coastguard Worker }
135*795d594fSAndroid Build Coastguard Worker 
Create(const std::string & name,size_t initial_size,size_t growth_limit,size_t capacity,bool low_memory_mode,bool can_move_objects)136*795d594fSAndroid Build Coastguard Worker RosAllocSpace* RosAllocSpace::Create(const std::string& name,
137*795d594fSAndroid Build Coastguard Worker                                      size_t initial_size,
138*795d594fSAndroid Build Coastguard Worker                                      size_t growth_limit,
139*795d594fSAndroid Build Coastguard Worker                                      size_t capacity,
140*795d594fSAndroid Build Coastguard Worker                                      bool low_memory_mode,
141*795d594fSAndroid Build Coastguard Worker                                      bool can_move_objects) {
142*795d594fSAndroid Build Coastguard Worker   uint64_t start_time = 0;
143*795d594fSAndroid Build Coastguard Worker   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
144*795d594fSAndroid Build Coastguard Worker     start_time = NanoTime();
145*795d594fSAndroid Build Coastguard Worker     VLOG(startup) << "RosAllocSpace::Create entering " << name
146*795d594fSAndroid Build Coastguard Worker                   << " initial_size=" << PrettySize(initial_size)
147*795d594fSAndroid Build Coastguard Worker                   << " growth_limit=" << PrettySize(growth_limit)
148*795d594fSAndroid Build Coastguard Worker                   << " capacity=" << PrettySize(capacity);
149*795d594fSAndroid Build Coastguard Worker   }
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker   // Memory we promise to rosalloc before it asks for morecore.
152*795d594fSAndroid Build Coastguard Worker   // Note: making this value large means that large allocations are unlikely to succeed as rosalloc
153*795d594fSAndroid Build Coastguard Worker   // will ask for this memory from sys_alloc which will fail as the footprint (this value plus the
154*795d594fSAndroid Build Coastguard Worker   // size of the large allocation) will be greater than the footprint limit.
155*795d594fSAndroid Build Coastguard Worker   size_t starting_size = Heap::GetDefaultStartingSize();
156*795d594fSAndroid Build Coastguard Worker   MemMap mem_map = CreateMemMap(name, starting_size, &initial_size, &growth_limit, &capacity);
157*795d594fSAndroid Build Coastguard Worker   if (!mem_map.IsValid()) {
158*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to create mem map for alloc space (" << name << ") of size "
159*795d594fSAndroid Build Coastguard Worker                << PrettySize(capacity);
160*795d594fSAndroid Build Coastguard Worker     return nullptr;
161*795d594fSAndroid Build Coastguard Worker   }
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker   RosAllocSpace* space = CreateFromMemMap(std::move(mem_map),
164*795d594fSAndroid Build Coastguard Worker                                           name,
165*795d594fSAndroid Build Coastguard Worker                                           starting_size,
166*795d594fSAndroid Build Coastguard Worker                                           initial_size,
167*795d594fSAndroid Build Coastguard Worker                                           growth_limit,
168*795d594fSAndroid Build Coastguard Worker                                           capacity,
169*795d594fSAndroid Build Coastguard Worker                                           low_memory_mode,
170*795d594fSAndroid Build Coastguard Worker                                           can_move_objects);
171*795d594fSAndroid Build Coastguard Worker   // We start out with only the initial size possibly containing objects.
172*795d594fSAndroid Build Coastguard Worker   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
173*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "RosAllocSpace::Create exiting (" << PrettyDuration(NanoTime() - start_time)
174*795d594fSAndroid Build Coastguard Worker         << " ) " << *space;
175*795d594fSAndroid Build Coastguard Worker   }
176*795d594fSAndroid Build Coastguard Worker   return space;
177*795d594fSAndroid Build Coastguard Worker }
178*795d594fSAndroid Build Coastguard Worker 
CreateRosAlloc(void * begin,size_t morecore_start,size_t initial_size,size_t maximum_size,bool low_memory_mode,bool running_on_memory_tool)179*795d594fSAndroid Build Coastguard Worker allocator::RosAlloc* RosAllocSpace::CreateRosAlloc(void* begin, size_t morecore_start,
180*795d594fSAndroid Build Coastguard Worker                                                    size_t initial_size,
181*795d594fSAndroid Build Coastguard Worker                                                    size_t maximum_size, bool low_memory_mode,
182*795d594fSAndroid Build Coastguard Worker                                                    bool running_on_memory_tool) {
183*795d594fSAndroid Build Coastguard Worker   // clear errno to allow PLOG on error
184*795d594fSAndroid Build Coastguard Worker   errno = 0;
185*795d594fSAndroid Build Coastguard Worker   // create rosalloc using our backing storage starting at begin and
186*795d594fSAndroid Build Coastguard Worker   // with a footprint of morecore_start. When morecore_start bytes of
187*795d594fSAndroid Build Coastguard Worker   // memory is exhaused morecore will be called.
188*795d594fSAndroid Build Coastguard Worker   allocator::RosAlloc* rosalloc = new art::gc::allocator::RosAlloc(
189*795d594fSAndroid Build Coastguard Worker       begin, morecore_start, maximum_size,
190*795d594fSAndroid Build Coastguard Worker       low_memory_mode ?
191*795d594fSAndroid Build Coastguard Worker           art::gc::allocator::RosAlloc::kPageReleaseModeAll :
192*795d594fSAndroid Build Coastguard Worker           art::gc::allocator::RosAlloc::kPageReleaseModeSizeAndEnd,
193*795d594fSAndroid Build Coastguard Worker       running_on_memory_tool);
194*795d594fSAndroid Build Coastguard Worker   if (rosalloc != nullptr) {
195*795d594fSAndroid Build Coastguard Worker     rosalloc->SetFootprintLimit(initial_size);
196*795d594fSAndroid Build Coastguard Worker   } else {
197*795d594fSAndroid Build Coastguard Worker     PLOG(ERROR) << "RosAlloc::Create failed";
198*795d594fSAndroid Build Coastguard Worker   }
199*795d594fSAndroid Build Coastguard Worker   return rosalloc;
200*795d594fSAndroid Build Coastguard Worker }
201*795d594fSAndroid Build Coastguard Worker 
AllocWithGrowth(Thread * self,size_t num_bytes,size_t * bytes_allocated,size_t * usable_size,size_t * bytes_tl_bulk_allocated)202*795d594fSAndroid Build Coastguard Worker mirror::Object* RosAllocSpace::AllocWithGrowth(Thread* self, size_t num_bytes,
203*795d594fSAndroid Build Coastguard Worker                                                size_t* bytes_allocated, size_t* usable_size,
204*795d594fSAndroid Build Coastguard Worker                                                size_t* bytes_tl_bulk_allocated) {
205*795d594fSAndroid Build Coastguard Worker   mirror::Object* result;
206*795d594fSAndroid Build Coastguard Worker   {
207*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, lock_);
208*795d594fSAndroid Build Coastguard Worker     // Grow as much as possible within the space.
209*795d594fSAndroid Build Coastguard Worker     size_t max_allowed = Capacity();
210*795d594fSAndroid Build Coastguard Worker     rosalloc_->SetFootprintLimit(max_allowed);
211*795d594fSAndroid Build Coastguard Worker     // Try the allocation.
212*795d594fSAndroid Build Coastguard Worker     result = AllocCommon(self, num_bytes, bytes_allocated, usable_size,
213*795d594fSAndroid Build Coastguard Worker                          bytes_tl_bulk_allocated);
214*795d594fSAndroid Build Coastguard Worker     // Shrink back down as small as possible.
215*795d594fSAndroid Build Coastguard Worker     size_t footprint = rosalloc_->Footprint();
216*795d594fSAndroid Build Coastguard Worker     rosalloc_->SetFootprintLimit(footprint);
217*795d594fSAndroid Build Coastguard Worker   }
218*795d594fSAndroid Build Coastguard Worker   // Note RosAlloc zeroes memory internally.
219*795d594fSAndroid Build Coastguard Worker   // Return the new allocation or null.
220*795d594fSAndroid Build Coastguard Worker   CHECK(!kDebugSpaces || result == nullptr || Contains(result));
221*795d594fSAndroid Build Coastguard Worker   return result;
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker 
CreateInstance(MemMap && mem_map,const std::string & name,void * allocator,uint8_t * begin,uint8_t * end,uint8_t * limit,size_t growth_limit,bool can_move_objects)224*795d594fSAndroid Build Coastguard Worker MallocSpace* RosAllocSpace::CreateInstance(MemMap&& mem_map,
225*795d594fSAndroid Build Coastguard Worker                                            const std::string& name,
226*795d594fSAndroid Build Coastguard Worker                                            void* allocator,
227*795d594fSAndroid Build Coastguard Worker                                            uint8_t* begin,
228*795d594fSAndroid Build Coastguard Worker                                            uint8_t* end,
229*795d594fSAndroid Build Coastguard Worker                                            uint8_t* limit,
230*795d594fSAndroid Build Coastguard Worker                                            size_t growth_limit,
231*795d594fSAndroid Build Coastguard Worker                                            bool can_move_objects) {
232*795d594fSAndroid Build Coastguard Worker   if (Runtime::Current()->IsRunningOnMemoryTool()) {
233*795d594fSAndroid Build Coastguard Worker     return new MemoryToolMallocSpace<RosAllocSpace, kDefaultMemoryToolRedZoneBytes, false, true>(
234*795d594fSAndroid Build Coastguard Worker         std::move(mem_map),
235*795d594fSAndroid Build Coastguard Worker         initial_size_,
236*795d594fSAndroid Build Coastguard Worker         name,
237*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<allocator::RosAlloc*>(allocator),
238*795d594fSAndroid Build Coastguard Worker         begin,
239*795d594fSAndroid Build Coastguard Worker         end,
240*795d594fSAndroid Build Coastguard Worker         limit,
241*795d594fSAndroid Build Coastguard Worker         growth_limit,
242*795d594fSAndroid Build Coastguard Worker         can_move_objects,
243*795d594fSAndroid Build Coastguard Worker         starting_size_,
244*795d594fSAndroid Build Coastguard Worker         low_memory_mode_);
245*795d594fSAndroid Build Coastguard Worker   } else {
246*795d594fSAndroid Build Coastguard Worker     return new RosAllocSpace(std::move(mem_map),
247*795d594fSAndroid Build Coastguard Worker                              initial_size_,
248*795d594fSAndroid Build Coastguard Worker                              name,
249*795d594fSAndroid Build Coastguard Worker                              reinterpret_cast<allocator::RosAlloc*>(allocator),
250*795d594fSAndroid Build Coastguard Worker                              begin,
251*795d594fSAndroid Build Coastguard Worker                              end,
252*795d594fSAndroid Build Coastguard Worker                              limit,
253*795d594fSAndroid Build Coastguard Worker                              growth_limit,
254*795d594fSAndroid Build Coastguard Worker                              can_move_objects,
255*795d594fSAndroid Build Coastguard Worker                              starting_size_,
256*795d594fSAndroid Build Coastguard Worker                              low_memory_mode_);
257*795d594fSAndroid Build Coastguard Worker   }
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker 
Free(Thread * self,mirror::Object * ptr)260*795d594fSAndroid Build Coastguard Worker size_t RosAllocSpace::Free(Thread* self, mirror::Object* ptr) {
261*795d594fSAndroid Build Coastguard Worker   if (kDebugSpaces) {
262*795d594fSAndroid Build Coastguard Worker     CHECK(ptr != nullptr);
263*795d594fSAndroid Build Coastguard Worker     CHECK(Contains(ptr)) << "Free (" << ptr << ") not in bounds of heap " << *this;
264*795d594fSAndroid Build Coastguard Worker   }
265*795d594fSAndroid Build Coastguard Worker   if (kRecentFreeCount > 0) {
266*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, lock_);
267*795d594fSAndroid Build Coastguard Worker     RegisterRecentFree(ptr);
268*795d594fSAndroid Build Coastguard Worker   }
269*795d594fSAndroid Build Coastguard Worker   return rosalloc_->Free(self, ptr);
270*795d594fSAndroid Build Coastguard Worker }
271*795d594fSAndroid Build Coastguard Worker 
FreeList(Thread * self,size_t num_ptrs,mirror::Object ** ptrs)272*795d594fSAndroid Build Coastguard Worker size_t RosAllocSpace::FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) {
273*795d594fSAndroid Build Coastguard Worker   DCHECK(ptrs != nullptr);
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   size_t verify_bytes = 0;
276*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < num_ptrs; i++) {
277*795d594fSAndroid Build Coastguard Worker     if (kPrefetchDuringRosAllocFreeList && i + kPrefetchLookAhead < num_ptrs) {
278*795d594fSAndroid Build Coastguard Worker       __builtin_prefetch(reinterpret_cast<char*>(ptrs[i + kPrefetchLookAhead]));
279*795d594fSAndroid Build Coastguard Worker     }
280*795d594fSAndroid Build Coastguard Worker     if (kVerifyFreedBytes) {
281*795d594fSAndroid Build Coastguard Worker       verify_bytes += AllocationSizeNonvirtual<true>(ptrs[i], nullptr);
282*795d594fSAndroid Build Coastguard Worker     }
283*795d594fSAndroid Build Coastguard Worker   }
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker   if (kRecentFreeCount > 0) {
286*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, lock_);
287*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < num_ptrs; i++) {
288*795d594fSAndroid Build Coastguard Worker       RegisterRecentFree(ptrs[i]);
289*795d594fSAndroid Build Coastguard Worker     }
290*795d594fSAndroid Build Coastguard Worker   }
291*795d594fSAndroid Build Coastguard Worker 
292*795d594fSAndroid Build Coastguard Worker   if (kDebugSpaces) {
293*795d594fSAndroid Build Coastguard Worker     size_t num_broken_ptrs = 0;
294*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < num_ptrs; i++) {
295*795d594fSAndroid Build Coastguard Worker       if (!Contains(ptrs[i])) {
296*795d594fSAndroid Build Coastguard Worker         num_broken_ptrs++;
297*795d594fSAndroid Build Coastguard Worker         LOG(ERROR) << "FreeList[" << i << "] (" << ptrs[i] << ") not in bounds of heap " << *this;
298*795d594fSAndroid Build Coastguard Worker       } else {
299*795d594fSAndroid Build Coastguard Worker         size_t size = rosalloc_->UsableSize(ptrs[i]);
300*795d594fSAndroid Build Coastguard Worker         memset(ptrs[i], 0xEF, size);
301*795d594fSAndroid Build Coastguard Worker       }
302*795d594fSAndroid Build Coastguard Worker     }
303*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(num_broken_ptrs, 0u);
304*795d594fSAndroid Build Coastguard Worker   }
305*795d594fSAndroid Build Coastguard Worker 
306*795d594fSAndroid Build Coastguard Worker   const size_t bytes_freed = rosalloc_->BulkFree(self, reinterpret_cast<void**>(ptrs), num_ptrs);
307*795d594fSAndroid Build Coastguard Worker   if (kVerifyFreedBytes) {
308*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(verify_bytes, bytes_freed);
309*795d594fSAndroid Build Coastguard Worker   }
310*795d594fSAndroid Build Coastguard Worker   return bytes_freed;
311*795d594fSAndroid Build Coastguard Worker }
312*795d594fSAndroid Build Coastguard Worker 
Trim()313*795d594fSAndroid Build Coastguard Worker size_t RosAllocSpace::Trim() {
314*795d594fSAndroid Build Coastguard Worker   VLOG(heap) << "RosAllocSpace::Trim() ";
315*795d594fSAndroid Build Coastguard Worker   {
316*795d594fSAndroid Build Coastguard Worker     Thread* const self = Thread::Current();
317*795d594fSAndroid Build Coastguard Worker     // SOA required for Rosalloc::Trim() -> ArtRosAllocMoreCore() -> Heap::GetRosAllocSpace.
318*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(self);
319*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, lock_);
320*795d594fSAndroid Build Coastguard Worker     // Trim to release memory at the end of the space.
321*795d594fSAndroid Build Coastguard Worker     rosalloc_->Trim();
322*795d594fSAndroid Build Coastguard Worker   }
323*795d594fSAndroid Build Coastguard Worker   // Attempt to release pages if it does not release all empty pages.
324*795d594fSAndroid Build Coastguard Worker   if (!rosalloc_->DoesReleaseAllPages()) {
325*795d594fSAndroid Build Coastguard Worker     return rosalloc_->ReleasePages();
326*795d594fSAndroid Build Coastguard Worker   }
327*795d594fSAndroid Build Coastguard Worker   return 0;
328*795d594fSAndroid Build Coastguard Worker }
329*795d594fSAndroid Build Coastguard Worker 
Walk(void (* callback)(void * start,void * end,size_t num_bytes,void * callback_arg),void * arg)330*795d594fSAndroid Build Coastguard Worker void RosAllocSpace::Walk(void(*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
331*795d594fSAndroid Build Coastguard Worker                          void* arg) {
332*795d594fSAndroid Build Coastguard Worker   InspectAllRosAlloc(callback, arg, true);
333*795d594fSAndroid Build Coastguard Worker }
334*795d594fSAndroid Build Coastguard Worker 
GetFootprint()335*795d594fSAndroid Build Coastguard Worker size_t RosAllocSpace::GetFootprint() {
336*795d594fSAndroid Build Coastguard Worker   MutexLock mu(Thread::Current(), lock_);
337*795d594fSAndroid Build Coastguard Worker   return rosalloc_->Footprint();
338*795d594fSAndroid Build Coastguard Worker }
339*795d594fSAndroid Build Coastguard Worker 
GetFootprintLimit()340*795d594fSAndroid Build Coastguard Worker size_t RosAllocSpace::GetFootprintLimit() {
341*795d594fSAndroid Build Coastguard Worker   MutexLock mu(Thread::Current(), lock_);
342*795d594fSAndroid Build Coastguard Worker   return rosalloc_->FootprintLimit();
343*795d594fSAndroid Build Coastguard Worker }
344*795d594fSAndroid Build Coastguard Worker 
SetFootprintLimit(size_t new_size)345*795d594fSAndroid Build Coastguard Worker void RosAllocSpace::SetFootprintLimit(size_t new_size) {
346*795d594fSAndroid Build Coastguard Worker   MutexLock mu(Thread::Current(), lock_);
347*795d594fSAndroid Build Coastguard Worker   VLOG(heap) << "RosAllocSpace::SetFootprintLimit " << PrettySize(new_size);
348*795d594fSAndroid Build Coastguard Worker   // Compare against the actual footprint, rather than the Size(), because the heap may not have
349*795d594fSAndroid Build Coastguard Worker   // grown all the way to the allowed size yet.
350*795d594fSAndroid Build Coastguard Worker   size_t current_space_size = rosalloc_->Footprint();
351*795d594fSAndroid Build Coastguard Worker   if (new_size < current_space_size) {
352*795d594fSAndroid Build Coastguard Worker     // Don't let the space grow any more.
353*795d594fSAndroid Build Coastguard Worker     new_size = current_space_size;
354*795d594fSAndroid Build Coastguard Worker   }
355*795d594fSAndroid Build Coastguard Worker   rosalloc_->SetFootprintLimit(new_size);
356*795d594fSAndroid Build Coastguard Worker }
357*795d594fSAndroid Build Coastguard Worker 
GetBytesAllocated()358*795d594fSAndroid Build Coastguard Worker uint64_t RosAllocSpace::GetBytesAllocated() {
359*795d594fSAndroid Build Coastguard Worker   size_t bytes_allocated = 0;
360*795d594fSAndroid Build Coastguard Worker   InspectAllRosAlloc(art::gc::allocator::RosAlloc::BytesAllocatedCallback, &bytes_allocated, false);
361*795d594fSAndroid Build Coastguard Worker   return bytes_allocated;
362*795d594fSAndroid Build Coastguard Worker }
363*795d594fSAndroid Build Coastguard Worker 
GetObjectsAllocated()364*795d594fSAndroid Build Coastguard Worker uint64_t RosAllocSpace::GetObjectsAllocated() {
365*795d594fSAndroid Build Coastguard Worker   size_t objects_allocated = 0;
366*795d594fSAndroid Build Coastguard Worker   InspectAllRosAlloc(art::gc::allocator::RosAlloc::ObjectsAllocatedCallback, &objects_allocated, false);
367*795d594fSAndroid Build Coastguard Worker   return objects_allocated;
368*795d594fSAndroid Build Coastguard Worker }
369*795d594fSAndroid Build Coastguard Worker 
InspectAllRosAllocWithSuspendAll(void (* callback)(void * start,void * end,size_t num_bytes,void * callback_arg),void * arg,bool do_null_callback_at_end)370*795d594fSAndroid Build Coastguard Worker void RosAllocSpace::InspectAllRosAllocWithSuspendAll(
371*795d594fSAndroid Build Coastguard Worker     void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
372*795d594fSAndroid Build Coastguard Worker     void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS {
373*795d594fSAndroid Build Coastguard Worker   // TODO: NO_THREAD_SAFETY_ANALYSIS.
374*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
375*795d594fSAndroid Build Coastguard Worker   ScopedSuspendAll ssa(__FUNCTION__);
376*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::runtime_shutdown_lock_);
377*795d594fSAndroid Build Coastguard Worker   MutexLock mu2(self, *Locks::thread_list_lock_);
378*795d594fSAndroid Build Coastguard Worker   rosalloc_->InspectAll(callback, arg);
379*795d594fSAndroid Build Coastguard Worker   if (do_null_callback_at_end) {
380*795d594fSAndroid Build Coastguard Worker     callback(nullptr, nullptr, 0, arg);  // Indicate end of a space.
381*795d594fSAndroid Build Coastguard Worker   }
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker 
InspectAllRosAlloc(void (* callback)(void * start,void * end,size_t num_bytes,void * callback_arg),void * arg,bool do_null_callback_at_end)384*795d594fSAndroid Build Coastguard Worker void RosAllocSpace::InspectAllRosAlloc(void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg),
385*795d594fSAndroid Build Coastguard Worker                                        void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS {
386*795d594fSAndroid Build Coastguard Worker   // TODO: NO_THREAD_SAFETY_ANALYSIS.
387*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
388*795d594fSAndroid Build Coastguard Worker   if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
389*795d594fSAndroid Build Coastguard Worker     // The mutators are already suspended. For example, a call path
390*795d594fSAndroid Build Coastguard Worker     // from SignalCatcher::HandleSigQuit().
391*795d594fSAndroid Build Coastguard Worker     rosalloc_->InspectAll(callback, arg);
392*795d594fSAndroid Build Coastguard Worker     if (do_null_callback_at_end) {
393*795d594fSAndroid Build Coastguard Worker       callback(nullptr, nullptr, 0, arg);  // Indicate end of a space.
394*795d594fSAndroid Build Coastguard Worker     }
395*795d594fSAndroid Build Coastguard Worker   } else if (Locks::mutator_lock_->IsSharedHeld(self)) {
396*795d594fSAndroid Build Coastguard Worker     // The mutators are not suspended yet and we have a shared access
397*795d594fSAndroid Build Coastguard Worker     // to the mutator lock. Temporarily release the shared access by
398*795d594fSAndroid Build Coastguard Worker     // transitioning to the suspend state, and suspend the mutators.
399*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
400*795d594fSAndroid Build Coastguard Worker     InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end);
401*795d594fSAndroid Build Coastguard Worker   } else {
402*795d594fSAndroid Build Coastguard Worker     // The mutators are not suspended yet. Suspend the mutators.
403*795d594fSAndroid Build Coastguard Worker     InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end);
404*795d594fSAndroid Build Coastguard Worker   }
405*795d594fSAndroid Build Coastguard Worker }
406*795d594fSAndroid Build Coastguard Worker 
RevokeThreadLocalBuffers(Thread * thread)407*795d594fSAndroid Build Coastguard Worker size_t RosAllocSpace::RevokeThreadLocalBuffers(Thread* thread) {
408*795d594fSAndroid Build Coastguard Worker   return rosalloc_->RevokeThreadLocalRuns(thread);
409*795d594fSAndroid Build Coastguard Worker }
410*795d594fSAndroid Build Coastguard Worker 
RevokeAllThreadLocalBuffers()411*795d594fSAndroid Build Coastguard Worker size_t RosAllocSpace::RevokeAllThreadLocalBuffers() {
412*795d594fSAndroid Build Coastguard Worker   return rosalloc_->RevokeAllThreadLocalRuns();
413*795d594fSAndroid Build Coastguard Worker }
414*795d594fSAndroid Build Coastguard Worker 
AssertThreadLocalBuffersAreRevoked(Thread * thread)415*795d594fSAndroid Build Coastguard Worker void RosAllocSpace::AssertThreadLocalBuffersAreRevoked(Thread* thread) {
416*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
417*795d594fSAndroid Build Coastguard Worker     rosalloc_->AssertThreadLocalRunsAreRevoked(thread);
418*795d594fSAndroid Build Coastguard Worker   }
419*795d594fSAndroid Build Coastguard Worker }
420*795d594fSAndroid Build Coastguard Worker 
AssertAllThreadLocalBuffersAreRevoked()421*795d594fSAndroid Build Coastguard Worker void RosAllocSpace::AssertAllThreadLocalBuffersAreRevoked() {
422*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
423*795d594fSAndroid Build Coastguard Worker     rosalloc_->AssertAllThreadLocalRunsAreRevoked();
424*795d594fSAndroid Build Coastguard Worker   }
425*795d594fSAndroid Build Coastguard Worker }
426*795d594fSAndroid Build Coastguard Worker 
Clear()427*795d594fSAndroid Build Coastguard Worker void RosAllocSpace::Clear() {
428*795d594fSAndroid Build Coastguard Worker   size_t footprint_limit = GetFootprintLimit();
429*795d594fSAndroid Build Coastguard Worker   madvise(GetMemMap()->Begin(), GetMemMap()->Size(), MADV_DONTNEED);
430*795d594fSAndroid Build Coastguard Worker   live_bitmap_.Clear();
431*795d594fSAndroid Build Coastguard Worker   mark_bitmap_.Clear();
432*795d594fSAndroid Build Coastguard Worker   SetEnd(begin_ + starting_size_);
433*795d594fSAndroid Build Coastguard Worker   delete rosalloc_;
434*795d594fSAndroid Build Coastguard Worker   rosalloc_ = CreateRosAlloc(mem_map_.Begin(),
435*795d594fSAndroid Build Coastguard Worker                              starting_size_,
436*795d594fSAndroid Build Coastguard Worker                              initial_size_,
437*795d594fSAndroid Build Coastguard Worker                              NonGrowthLimitCapacity(),
438*795d594fSAndroid Build Coastguard Worker                              low_memory_mode_,
439*795d594fSAndroid Build Coastguard Worker                              Runtime::Current()->IsRunningOnMemoryTool());
440*795d594fSAndroid Build Coastguard Worker   SetFootprintLimit(footprint_limit);
441*795d594fSAndroid Build Coastguard Worker }
442*795d594fSAndroid Build Coastguard Worker 
DumpStats(std::ostream & os)443*795d594fSAndroid Build Coastguard Worker void RosAllocSpace::DumpStats(std::ostream& os) {
444*795d594fSAndroid Build Coastguard Worker   ScopedSuspendAll ssa(__FUNCTION__);
445*795d594fSAndroid Build Coastguard Worker   rosalloc_->DumpStats(os);
446*795d594fSAndroid Build Coastguard Worker }
447*795d594fSAndroid Build Coastguard Worker 
448*795d594fSAndroid Build Coastguard Worker template<bool kMaybeIsRunningOnMemoryTool>
AllocationSizeNonvirtual(mirror::Object * obj,size_t * usable_size)449*795d594fSAndroid Build Coastguard Worker size_t RosAllocSpace::AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size) {
450*795d594fSAndroid Build Coastguard Worker   // obj is a valid object. Use its class in the header to get the size.
451*795d594fSAndroid Build Coastguard Worker   // Don't use verification since the object may be dead if we are sweeping.
452*795d594fSAndroid Build Coastguard Worker   size_t size = obj->SizeOf<kVerifyNone>();
453*795d594fSAndroid Build Coastguard Worker   bool add_redzones = false;
454*795d594fSAndroid Build Coastguard Worker   if (kMaybeIsRunningOnMemoryTool) {
455*795d594fSAndroid Build Coastguard Worker     add_redzones = kRunningOnMemoryTool && kMemoryToolAddsRedzones;
456*795d594fSAndroid Build Coastguard Worker     if (add_redzones) {
457*795d594fSAndroid Build Coastguard Worker       size += 2 * kDefaultMemoryToolRedZoneBytes;
458*795d594fSAndroid Build Coastguard Worker     }
459*795d594fSAndroid Build Coastguard Worker   } else {
460*795d594fSAndroid Build Coastguard Worker     DCHECK(!kRunningOnMemoryTool);
461*795d594fSAndroid Build Coastguard Worker   }
462*795d594fSAndroid Build Coastguard Worker   size_t size_by_size = rosalloc_->UsableSize(size);
463*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
464*795d594fSAndroid Build Coastguard Worker     // On memory tool, the red zone has an impact...
465*795d594fSAndroid Build Coastguard Worker     const uint8_t* obj_ptr = reinterpret_cast<const uint8_t*>(obj);
466*795d594fSAndroid Build Coastguard Worker     size_t size_by_ptr = rosalloc_->UsableSize(
467*795d594fSAndroid Build Coastguard Worker         obj_ptr - (add_redzones ? kDefaultMemoryToolRedZoneBytes : 0));
468*795d594fSAndroid Build Coastguard Worker     if (size_by_size != size_by_ptr) {
469*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "Found a bad sized obj of size " << size
470*795d594fSAndroid Build Coastguard Worker                 << " at " << std::hex << reinterpret_cast<intptr_t>(obj_ptr) << std::dec
471*795d594fSAndroid Build Coastguard Worker                 << " size_by_size=" << size_by_size << " size_by_ptr=" << size_by_ptr;
472*795d594fSAndroid Build Coastguard Worker     }
473*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(size_by_size, size_by_ptr);
474*795d594fSAndroid Build Coastguard Worker   }
475*795d594fSAndroid Build Coastguard Worker   if (usable_size != nullptr) {
476*795d594fSAndroid Build Coastguard Worker     *usable_size = size_by_size;
477*795d594fSAndroid Build Coastguard Worker   }
478*795d594fSAndroid Build Coastguard Worker   return size_by_size;
479*795d594fSAndroid Build Coastguard Worker }
480*795d594fSAndroid Build Coastguard Worker 
481*795d594fSAndroid Build Coastguard Worker }  // namespace space
482*795d594fSAndroid Build Coastguard Worker 
483*795d594fSAndroid Build Coastguard Worker namespace allocator {
484*795d594fSAndroid Build Coastguard Worker 
485*795d594fSAndroid Build Coastguard Worker // Callback from rosalloc when it needs to increase the footprint.
ArtRosAllocMoreCore(allocator::RosAlloc * rosalloc,intptr_t increment)486*795d594fSAndroid Build Coastguard Worker void* ArtRosAllocMoreCore(allocator::RosAlloc* rosalloc, intptr_t increment)
487*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
488*795d594fSAndroid Build Coastguard Worker   Heap* heap = Runtime::Current()->GetHeap();
489*795d594fSAndroid Build Coastguard Worker   art::gc::space::RosAllocSpace* rosalloc_space = heap->GetRosAllocSpace(rosalloc);
490*795d594fSAndroid Build Coastguard Worker   DCHECK(rosalloc_space != nullptr);
491*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(rosalloc_space->GetRosAlloc(), rosalloc);
492*795d594fSAndroid Build Coastguard Worker   return rosalloc_space->MoreCore(increment);
493*795d594fSAndroid Build Coastguard Worker }
494*795d594fSAndroid Build Coastguard Worker 
495*795d594fSAndroid Build Coastguard Worker }  // namespace allocator
496*795d594fSAndroid Build Coastguard Worker 
497*795d594fSAndroid Build Coastguard Worker }  // namespace gc
498*795d594fSAndroid Build Coastguard Worker }  // namespace art
499