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 #include "bump_pointer_space.h"
18*795d594fSAndroid Build Coastguard Worker #include "bump_pointer_space-inl.h"
19*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
20*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
24*795d594fSAndroid Build Coastguard Worker namespace gc {
25*795d594fSAndroid Build Coastguard Worker namespace space {
26*795d594fSAndroid Build Coastguard Worker
Create(const std::string & name,size_t capacity)27*795d594fSAndroid Build Coastguard Worker BumpPointerSpace* BumpPointerSpace::Create(const std::string& name, size_t capacity) {
28*795d594fSAndroid Build Coastguard Worker capacity = RoundUp(capacity, gPageSize);
29*795d594fSAndroid Build Coastguard Worker std::string error_msg;
30*795d594fSAndroid Build Coastguard Worker MemMap mem_map = MemMap::MapAnonymous(name.c_str(),
31*795d594fSAndroid Build Coastguard Worker capacity,
32*795d594fSAndroid Build Coastguard Worker PROT_READ | PROT_WRITE,
33*795d594fSAndroid Build Coastguard Worker /*low_4gb=*/ true,
34*795d594fSAndroid Build Coastguard Worker &error_msg);
35*795d594fSAndroid Build Coastguard Worker if (!mem_map.IsValid()) {
36*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to allocate pages for alloc space (" << name << ") of size "
37*795d594fSAndroid Build Coastguard Worker << PrettySize(capacity) << " with message " << error_msg;
38*795d594fSAndroid Build Coastguard Worker return nullptr;
39*795d594fSAndroid Build Coastguard Worker }
40*795d594fSAndroid Build Coastguard Worker return new BumpPointerSpace(name, std::move(mem_map));
41*795d594fSAndroid Build Coastguard Worker }
42*795d594fSAndroid Build Coastguard Worker
CreateFromMemMap(const std::string & name,MemMap && mem_map)43*795d594fSAndroid Build Coastguard Worker BumpPointerSpace* BumpPointerSpace::CreateFromMemMap(const std::string& name, MemMap&& mem_map) {
44*795d594fSAndroid Build Coastguard Worker return new BumpPointerSpace(name, std::move(mem_map));
45*795d594fSAndroid Build Coastguard Worker }
46*795d594fSAndroid Build Coastguard Worker
BumpPointerSpace(const std::string & name,uint8_t * begin,uint8_t * limit)47*795d594fSAndroid Build Coastguard Worker BumpPointerSpace::BumpPointerSpace(const std::string& name, uint8_t* begin, uint8_t* limit)
48*795d594fSAndroid Build Coastguard Worker : ContinuousMemMapAllocSpace(
49*795d594fSAndroid Build Coastguard Worker name, MemMap::Invalid(), begin, begin, limit, kGcRetentionPolicyAlwaysCollect),
50*795d594fSAndroid Build Coastguard Worker growth_end_(limit),
51*795d594fSAndroid Build Coastguard Worker objects_allocated_(0),
52*795d594fSAndroid Build Coastguard Worker bytes_allocated_(0),
53*795d594fSAndroid Build Coastguard Worker lock_("Bump-pointer space lock"),
54*795d594fSAndroid Build Coastguard Worker main_block_size_(0) {
55*795d594fSAndroid Build Coastguard Worker // This constructor gets called only from Heap::PreZygoteFork(), which
56*795d594fSAndroid Build Coastguard Worker // doesn't require a mark_bitmap.
57*795d594fSAndroid Build Coastguard Worker }
58*795d594fSAndroid Build Coastguard Worker
BumpPointerSpace(const std::string & name,MemMap && mem_map)59*795d594fSAndroid Build Coastguard Worker BumpPointerSpace::BumpPointerSpace(const std::string& name, MemMap&& mem_map)
60*795d594fSAndroid Build Coastguard Worker : ContinuousMemMapAllocSpace(name,
61*795d594fSAndroid Build Coastguard Worker std::move(mem_map),
62*795d594fSAndroid Build Coastguard Worker mem_map.Begin(),
63*795d594fSAndroid Build Coastguard Worker mem_map.Begin(),
64*795d594fSAndroid Build Coastguard Worker mem_map.End(),
65*795d594fSAndroid Build Coastguard Worker kGcRetentionPolicyAlwaysCollect),
66*795d594fSAndroid Build Coastguard Worker growth_end_(mem_map_.End()),
67*795d594fSAndroid Build Coastguard Worker objects_allocated_(0),
68*795d594fSAndroid Build Coastguard Worker bytes_allocated_(0),
69*795d594fSAndroid Build Coastguard Worker lock_("Bump-pointer space lock", kBumpPointerSpaceBlockLock),
70*795d594fSAndroid Build Coastguard Worker main_block_size_(0) {
71*795d594fSAndroid Build Coastguard Worker mark_bitmap_ =
72*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap::Create("bump-pointer space live bitmap",
73*795d594fSAndroid Build Coastguard Worker Begin(),
74*795d594fSAndroid Build Coastguard Worker Capacity());
75*795d594fSAndroid Build Coastguard Worker }
76*795d594fSAndroid Build Coastguard Worker
Clear()77*795d594fSAndroid Build Coastguard Worker void BumpPointerSpace::Clear() {
78*795d594fSAndroid Build Coastguard Worker // Release the pages back to the operating system.
79*795d594fSAndroid Build Coastguard Worker if (!kMadviseZeroes) {
80*795d594fSAndroid Build Coastguard Worker memset(Begin(), 0, Limit() - Begin());
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker CHECK_NE(madvise(Begin(), Limit() - Begin(), MADV_DONTNEED), -1) << "madvise failed";
83*795d594fSAndroid Build Coastguard Worker // Reset the end of the space back to the beginning, we move the end forward as we allocate
84*795d594fSAndroid Build Coastguard Worker // objects.
85*795d594fSAndroid Build Coastguard Worker SetEnd(Begin());
86*795d594fSAndroid Build Coastguard Worker objects_allocated_.store(0, std::memory_order_relaxed);
87*795d594fSAndroid Build Coastguard Worker bytes_allocated_.store(0, std::memory_order_relaxed);
88*795d594fSAndroid Build Coastguard Worker {
89*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), lock_);
90*795d594fSAndroid Build Coastguard Worker growth_end_ = Limit();
91*795d594fSAndroid Build Coastguard Worker block_sizes_.clear();
92*795d594fSAndroid Build Coastguard Worker main_block_size_ = 0;
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker
ClampGrowthLimit(size_t new_capacity)96*795d594fSAndroid Build Coastguard Worker size_t BumpPointerSpace::ClampGrowthLimit(size_t new_capacity) {
97*795d594fSAndroid Build Coastguard Worker CHECK(gUseUserfaultfd);
98*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), lock_);
99*795d594fSAndroid Build Coastguard Worker CHECK_EQ(growth_end_, Limit());
100*795d594fSAndroid Build Coastguard Worker uint8_t* end = End();
101*795d594fSAndroid Build Coastguard Worker CHECK_LE(end, growth_end_);
102*795d594fSAndroid Build Coastguard Worker size_t free_capacity = growth_end_ - end;
103*795d594fSAndroid Build Coastguard Worker size_t clamp_size = Capacity() - new_capacity;
104*795d594fSAndroid Build Coastguard Worker if (clamp_size > free_capacity) {
105*795d594fSAndroid Build Coastguard Worker new_capacity += clamp_size - free_capacity;
106*795d594fSAndroid Build Coastguard Worker }
107*795d594fSAndroid Build Coastguard Worker SetLimit(Begin() + new_capacity);
108*795d594fSAndroid Build Coastguard Worker growth_end_ = Limit();
109*795d594fSAndroid Build Coastguard Worker GetMemMap()->SetSize(new_capacity);
110*795d594fSAndroid Build Coastguard Worker if (GetMarkBitmap()->HeapBegin() != 0) {
111*795d594fSAndroid Build Coastguard Worker GetMarkBitmap()->SetHeapSize(new_capacity);
112*795d594fSAndroid Build Coastguard Worker }
113*795d594fSAndroid Build Coastguard Worker return new_capacity;
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker
Dump(std::ostream & os) const116*795d594fSAndroid Build Coastguard Worker void BumpPointerSpace::Dump(std::ostream& os) const {
117*795d594fSAndroid Build Coastguard Worker os << GetName() << " "
118*795d594fSAndroid Build Coastguard Worker << reinterpret_cast<void*>(Begin()) << "-" << reinterpret_cast<void*>(End()) << " - "
119*795d594fSAndroid Build Coastguard Worker << reinterpret_cast<void*>(Limit());
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker
RevokeThreadLocalBuffers(Thread * thread)122*795d594fSAndroid Build Coastguard Worker size_t BumpPointerSpace::RevokeThreadLocalBuffers(Thread* thread) {
123*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), lock_);
124*795d594fSAndroid Build Coastguard Worker RevokeThreadLocalBuffersLocked(thread);
125*795d594fSAndroid Build Coastguard Worker return 0U;
126*795d594fSAndroid Build Coastguard Worker }
127*795d594fSAndroid Build Coastguard Worker
RevokeAllThreadLocalBuffers()128*795d594fSAndroid Build Coastguard Worker size_t BumpPointerSpace::RevokeAllThreadLocalBuffers() {
129*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
130*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::runtime_shutdown_lock_);
131*795d594fSAndroid Build Coastguard Worker MutexLock mu2(self, *Locks::thread_list_lock_);
132*795d594fSAndroid Build Coastguard Worker // TODO: Not do a copy of the thread list?
133*795d594fSAndroid Build Coastguard Worker std::list<Thread*> thread_list = Runtime::Current()->GetThreadList()->GetList();
134*795d594fSAndroid Build Coastguard Worker for (Thread* thread : thread_list) {
135*795d594fSAndroid Build Coastguard Worker RevokeThreadLocalBuffers(thread);
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker return 0U;
138*795d594fSAndroid Build Coastguard Worker }
139*795d594fSAndroid Build Coastguard Worker
AssertThreadLocalBuffersAreRevoked(Thread * thread)140*795d594fSAndroid Build Coastguard Worker void BumpPointerSpace::AssertThreadLocalBuffersAreRevoked(Thread* thread) {
141*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
142*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), lock_);
143*795d594fSAndroid Build Coastguard Worker DCHECK(!thread->HasTlab());
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker }
146*795d594fSAndroid Build Coastguard Worker
AssertAllThreadLocalBuffersAreRevoked()147*795d594fSAndroid Build Coastguard Worker void BumpPointerSpace::AssertAllThreadLocalBuffersAreRevoked() {
148*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
149*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
150*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::runtime_shutdown_lock_);
151*795d594fSAndroid Build Coastguard Worker MutexLock mu2(self, *Locks::thread_list_lock_);
152*795d594fSAndroid Build Coastguard Worker // TODO: Not do a copy of the thread list?
153*795d594fSAndroid Build Coastguard Worker std::list<Thread*> thread_list = Runtime::Current()->GetThreadList()->GetList();
154*795d594fSAndroid Build Coastguard Worker for (Thread* thread : thread_list) {
155*795d594fSAndroid Build Coastguard Worker AssertThreadLocalBuffersAreRevoked(thread);
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker }
158*795d594fSAndroid Build Coastguard Worker }
159*795d594fSAndroid Build Coastguard Worker
UpdateMainBlock()160*795d594fSAndroid Build Coastguard Worker void BumpPointerSpace::UpdateMainBlock() {
161*795d594fSAndroid Build Coastguard Worker DCHECK(block_sizes_.empty());
162*795d594fSAndroid Build Coastguard Worker main_block_size_ = Size();
163*795d594fSAndroid Build Coastguard Worker }
164*795d594fSAndroid Build Coastguard Worker
165*795d594fSAndroid Build Coastguard Worker // Returns the start of the storage.
AllocBlock(size_t bytes)166*795d594fSAndroid Build Coastguard Worker uint8_t* BumpPointerSpace::AllocBlock(size_t bytes) {
167*795d594fSAndroid Build Coastguard Worker if (block_sizes_.empty()) {
168*795d594fSAndroid Build Coastguard Worker UpdateMainBlock();
169*795d594fSAndroid Build Coastguard Worker }
170*795d594fSAndroid Build Coastguard Worker uint8_t* storage = reinterpret_cast<uint8_t*>(AllocNonvirtualWithoutAccounting(bytes));
171*795d594fSAndroid Build Coastguard Worker if (LIKELY(storage != nullptr)) {
172*795d594fSAndroid Build Coastguard Worker block_sizes_.push_back(bytes);
173*795d594fSAndroid Build Coastguard Worker }
174*795d594fSAndroid Build Coastguard Worker return storage;
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker
GetSweepCallback()177*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap::SweepCallback* BumpPointerSpace::GetSweepCallback() {
178*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL);
179*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
180*795d594fSAndroid Build Coastguard Worker }
181*795d594fSAndroid Build Coastguard Worker
GetBytesAllocated()182*795d594fSAndroid Build Coastguard Worker uint64_t BumpPointerSpace::GetBytesAllocated() {
183*795d594fSAndroid Build Coastguard Worker // Start out pre-determined amount (blocks which are not being allocated into).
184*795d594fSAndroid Build Coastguard Worker uint64_t total = static_cast<uint64_t>(bytes_allocated_.load(std::memory_order_relaxed));
185*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
186*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::runtime_shutdown_lock_);
187*795d594fSAndroid Build Coastguard Worker MutexLock mu2(self, *Locks::thread_list_lock_);
188*795d594fSAndroid Build Coastguard Worker std::list<Thread*> thread_list = Runtime::Current()->GetThreadList()->GetList();
189*795d594fSAndroid Build Coastguard Worker MutexLock mu3(Thread::Current(), lock_);
190*795d594fSAndroid Build Coastguard Worker // If we don't have any blocks, we don't have any thread local buffers. This check is required
191*795d594fSAndroid Build Coastguard Worker // since there can exist multiple bump pointer spaces which exist at the same time.
192*795d594fSAndroid Build Coastguard Worker if (!block_sizes_.empty()) {
193*795d594fSAndroid Build Coastguard Worker for (Thread* thread : thread_list) {
194*795d594fSAndroid Build Coastguard Worker total += thread->GetThreadLocalBytesAllocated();
195*795d594fSAndroid Build Coastguard Worker }
196*795d594fSAndroid Build Coastguard Worker }
197*795d594fSAndroid Build Coastguard Worker return total;
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker
GetObjectsAllocated()200*795d594fSAndroid Build Coastguard Worker uint64_t BumpPointerSpace::GetObjectsAllocated() {
201*795d594fSAndroid Build Coastguard Worker // Start out pre-determined amount (blocks which are not being allocated into).
202*795d594fSAndroid Build Coastguard Worker uint64_t total = static_cast<uint64_t>(objects_allocated_.load(std::memory_order_relaxed));
203*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
204*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::runtime_shutdown_lock_);
205*795d594fSAndroid Build Coastguard Worker MutexLock mu2(self, *Locks::thread_list_lock_);
206*795d594fSAndroid Build Coastguard Worker std::list<Thread*> thread_list = Runtime::Current()->GetThreadList()->GetList();
207*795d594fSAndroid Build Coastguard Worker MutexLock mu3(Thread::Current(), lock_);
208*795d594fSAndroid Build Coastguard Worker // If we don't have any blocks, we don't have any thread local buffers. This check is required
209*795d594fSAndroid Build Coastguard Worker // since there can exist multiple bump pointer spaces which exist at the same time.
210*795d594fSAndroid Build Coastguard Worker if (!block_sizes_.empty()) {
211*795d594fSAndroid Build Coastguard Worker for (Thread* thread : thread_list) {
212*795d594fSAndroid Build Coastguard Worker total += thread->GetThreadLocalObjectsAllocated();
213*795d594fSAndroid Build Coastguard Worker }
214*795d594fSAndroid Build Coastguard Worker }
215*795d594fSAndroid Build Coastguard Worker return total;
216*795d594fSAndroid Build Coastguard Worker }
217*795d594fSAndroid Build Coastguard Worker
RevokeThreadLocalBuffersLocked(Thread * thread)218*795d594fSAndroid Build Coastguard Worker void BumpPointerSpace::RevokeThreadLocalBuffersLocked(Thread* thread) {
219*795d594fSAndroid Build Coastguard Worker objects_allocated_.fetch_add(thread->GetThreadLocalObjectsAllocated(), std::memory_order_relaxed);
220*795d594fSAndroid Build Coastguard Worker bytes_allocated_.fetch_add(thread->GetThreadLocalBytesAllocated(), std::memory_order_relaxed);
221*795d594fSAndroid Build Coastguard Worker thread->ResetTlab();
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker
AllocNewTlab(Thread * self,size_t bytes,size_t * bytes_tl_bulk_allocated)224*795d594fSAndroid Build Coastguard Worker bool BumpPointerSpace::AllocNewTlab(Thread* self, size_t bytes, size_t* bytes_tl_bulk_allocated) {
225*795d594fSAndroid Build Coastguard Worker bytes = RoundUp(bytes, kAlignment);
226*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), lock_);
227*795d594fSAndroid Build Coastguard Worker RevokeThreadLocalBuffersLocked(self);
228*795d594fSAndroid Build Coastguard Worker uint8_t* start = AllocBlock(bytes);
229*795d594fSAndroid Build Coastguard Worker if (start == nullptr) {
230*795d594fSAndroid Build Coastguard Worker return false;
231*795d594fSAndroid Build Coastguard Worker }
232*795d594fSAndroid Build Coastguard Worker self->SetTlab(start, start + bytes, start + bytes);
233*795d594fSAndroid Build Coastguard Worker if (bytes_tl_bulk_allocated != nullptr) {
234*795d594fSAndroid Build Coastguard Worker *bytes_tl_bulk_allocated = bytes;
235*795d594fSAndroid Build Coastguard Worker }
236*795d594fSAndroid Build Coastguard Worker return true;
237*795d594fSAndroid Build Coastguard Worker }
238*795d594fSAndroid Build Coastguard Worker
LogFragmentationAllocFailure(std::ostream & os,size_t failed_alloc_bytes)239*795d594fSAndroid Build Coastguard Worker bool BumpPointerSpace::LogFragmentationAllocFailure(std::ostream& os,
240*795d594fSAndroid Build Coastguard Worker size_t failed_alloc_bytes) {
241*795d594fSAndroid Build Coastguard Worker size_t max_contiguous_allocation = Limit() - End();
242*795d594fSAndroid Build Coastguard Worker if (failed_alloc_bytes > max_contiguous_allocation) {
243*795d594fSAndroid Build Coastguard Worker os << "; failed due to fragmentation (largest possible contiguous allocation "
244*795d594fSAndroid Build Coastguard Worker << max_contiguous_allocation << " bytes)";
245*795d594fSAndroid Build Coastguard Worker return true;
246*795d594fSAndroid Build Coastguard Worker }
247*795d594fSAndroid Build Coastguard Worker // Caller's job to print failed_alloc_bytes.
248*795d594fSAndroid Build Coastguard Worker return false;
249*795d594fSAndroid Build Coastguard Worker }
250*795d594fSAndroid Build Coastguard Worker
AllocationSizeNonvirtual(mirror::Object * obj,size_t * usable_size)251*795d594fSAndroid Build Coastguard Worker size_t BumpPointerSpace::AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size) {
252*795d594fSAndroid Build Coastguard Worker size_t num_bytes = obj->SizeOf();
253*795d594fSAndroid Build Coastguard Worker if (usable_size != nullptr) {
254*795d594fSAndroid Build Coastguard Worker *usable_size = RoundUp(num_bytes, kAlignment);
255*795d594fSAndroid Build Coastguard Worker }
256*795d594fSAndroid Build Coastguard Worker return num_bytes;
257*795d594fSAndroid Build Coastguard Worker }
258*795d594fSAndroid Build Coastguard Worker
AlignEnd(Thread * self,size_t alignment,Heap * heap)259*795d594fSAndroid Build Coastguard Worker uint8_t* BumpPointerSpace::AlignEnd(Thread* self, size_t alignment, Heap* heap) {
260*795d594fSAndroid Build Coastguard Worker Locks::mutator_lock_->AssertExclusiveHeld(self);
261*795d594fSAndroid Build Coastguard Worker DCHECK(IsAligned<kAlignment>(alignment));
262*795d594fSAndroid Build Coastguard Worker uint8_t* end = end_.load(std::memory_order_relaxed);
263*795d594fSAndroid Build Coastguard Worker uint8_t* aligned_end = AlignUp(end, alignment);
264*795d594fSAndroid Build Coastguard Worker ptrdiff_t diff = aligned_end - end;
265*795d594fSAndroid Build Coastguard Worker if (diff > 0) {
266*795d594fSAndroid Build Coastguard Worker end_.store(aligned_end, std::memory_order_relaxed);
267*795d594fSAndroid Build Coastguard Worker heap->AddBytesAllocated(diff);
268*795d594fSAndroid Build Coastguard Worker // If we have blocks after the main one. Then just add the diff to the last
269*795d594fSAndroid Build Coastguard Worker // block.
270*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, lock_);
271*795d594fSAndroid Build Coastguard Worker if (!block_sizes_.empty()) {
272*795d594fSAndroid Build Coastguard Worker block_sizes_.back() += diff;
273*795d594fSAndroid Build Coastguard Worker }
274*795d594fSAndroid Build Coastguard Worker }
275*795d594fSAndroid Build Coastguard Worker return aligned_end;
276*795d594fSAndroid Build Coastguard Worker }
277*795d594fSAndroid Build Coastguard Worker
GetBlockSizes(Thread * self,size_t * main_block_size)278*795d594fSAndroid Build Coastguard Worker std::vector<size_t>* BumpPointerSpace::GetBlockSizes(Thread* self, size_t* main_block_size) {
279*795d594fSAndroid Build Coastguard Worker std::vector<size_t>* block_sizes = nullptr;
280*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, lock_);
281*795d594fSAndroid Build Coastguard Worker if (!block_sizes_.empty()) {
282*795d594fSAndroid Build Coastguard Worker block_sizes = new std::vector<size_t>(block_sizes_.begin(), block_sizes_.end());
283*795d594fSAndroid Build Coastguard Worker } else {
284*795d594fSAndroid Build Coastguard Worker UpdateMainBlock();
285*795d594fSAndroid Build Coastguard Worker }
286*795d594fSAndroid Build Coastguard Worker *main_block_size = main_block_size_;
287*795d594fSAndroid Build Coastguard Worker return block_sizes;
288*795d594fSAndroid Build Coastguard Worker }
289*795d594fSAndroid Build Coastguard Worker
SetBlockSizes(Thread * self,const size_t main_block_size,const size_t first_valid_idx)290*795d594fSAndroid Build Coastguard Worker void BumpPointerSpace::SetBlockSizes(Thread* self,
291*795d594fSAndroid Build Coastguard Worker const size_t main_block_size,
292*795d594fSAndroid Build Coastguard Worker const size_t first_valid_idx) {
293*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, lock_);
294*795d594fSAndroid Build Coastguard Worker main_block_size_ = main_block_size;
295*795d594fSAndroid Build Coastguard Worker if (!block_sizes_.empty()) {
296*795d594fSAndroid Build Coastguard Worker block_sizes_.erase(block_sizes_.begin(), block_sizes_.begin() + first_valid_idx);
297*795d594fSAndroid Build Coastguard Worker }
298*795d594fSAndroid Build Coastguard Worker size_t size = main_block_size;
299*795d594fSAndroid Build Coastguard Worker for (size_t block_size : block_sizes_) {
300*795d594fSAndroid Build Coastguard Worker size += block_size;
301*795d594fSAndroid Build Coastguard Worker }
302*795d594fSAndroid Build Coastguard Worker DCHECK(IsAligned<kAlignment>(size));
303*795d594fSAndroid Build Coastguard Worker end_.store(Begin() + size, std::memory_order_relaxed);
304*795d594fSAndroid Build Coastguard Worker }
305*795d594fSAndroid Build Coastguard Worker
SetBlackDenseRegionSize(size_t size)306*795d594fSAndroid Build Coastguard Worker void BumpPointerSpace::SetBlackDenseRegionSize(size_t size) {
307*795d594fSAndroid Build Coastguard Worker DCHECK_ALIGNED_PARAM(size, gPageSize);
308*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), lock_);
309*795d594fSAndroid Build Coastguard Worker black_dense_region_size_ = size;
310*795d594fSAndroid Build Coastguard Worker }
311*795d594fSAndroid Build Coastguard Worker
312*795d594fSAndroid Build Coastguard Worker } // namespace space
313*795d594fSAndroid Build Coastguard Worker } // namespace gc
314*795d594fSAndroid Build Coastguard Worker } // namespace art
315