1/*
2 * Copyright (C) 2013 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#include "rosalloc.h"
18
19#include "base/memory_tool.h"
20#include "base/mutex-inl.h"
21#include "gc/space/memory_tool_settings.h"
22#include "mem_map.h"
23#include "mirror/class-inl.h"
24#include "mirror/object.h"
25#include "mirror/object-inl.h"
26#include "thread-inl.h"
27#include "thread_list.h"
28
29#include <map>
30#include <list>
31#include <sstream>
32#include <vector>
33
34namespace art {
35namespace gc {
36namespace allocator {
37
38static constexpr bool kUsePrefetchDuringAllocRun = false;
39static constexpr bool kPrefetchNewRunDataByZeroing = false;
40static constexpr size_t kPrefetchStride = 64;
41
42size_t RosAlloc::bracketSizes[kNumOfSizeBrackets];
43size_t RosAlloc::numOfPages[kNumOfSizeBrackets];
44size_t RosAlloc::numOfSlots[kNumOfSizeBrackets];
45size_t RosAlloc::headerSizes[kNumOfSizeBrackets];
46bool RosAlloc::initialized_ = false;
47size_t RosAlloc::dedicated_full_run_storage_[kPageSize / sizeof(size_t)] = { 0 };
48RosAlloc::Run* RosAlloc::dedicated_full_run_ =
49    reinterpret_cast<RosAlloc::Run*>(dedicated_full_run_storage_);
50
51RosAlloc::RosAlloc(void* base, size_t capacity, size_t max_capacity,
52                   PageReleaseMode page_release_mode, bool running_on_memory_tool,
53                   size_t page_release_size_threshold)
54    : base_(reinterpret_cast<uint8_t*>(base)), footprint_(capacity),
55      capacity_(capacity), max_capacity_(max_capacity),
56      lock_("rosalloc global lock", kRosAllocGlobalLock),
57      bulk_free_lock_("rosalloc bulk free lock", kRosAllocBulkFreeLock),
58      page_release_mode_(page_release_mode),
59      page_release_size_threshold_(page_release_size_threshold),
60      is_running_on_memory_tool_(running_on_memory_tool) {
61  DCHECK_ALIGNED(base, kPageSize);
62  DCHECK_EQ(RoundUp(capacity, kPageSize), capacity);
63  DCHECK_EQ(RoundUp(max_capacity, kPageSize), max_capacity);
64  CHECK_LE(capacity, max_capacity);
65  CHECK_ALIGNED(page_release_size_threshold_, kPageSize);
66  // Zero the memory explicitly (don't rely on that the mem map is zero-initialized).
67  if (!kMadviseZeroes) {
68    memset(base_, 0, max_capacity);
69  }
70  CHECK_EQ(madvise(base_, max_capacity, MADV_DONTNEED), 0);
71  if (!initialized_) {
72    Initialize();
73  }
74  VLOG(heap) << "RosAlloc base="
75             << std::hex << (intptr_t)base_ << ", end="
76             << std::hex << (intptr_t)(base_ + capacity_)
77             << ", capacity=" << std::dec << capacity_
78             << ", max_capacity=" << std::dec << max_capacity_;
79  for (size_t i = 0; i < kNumOfSizeBrackets; i++) {
80    size_bracket_lock_names_[i] =
81        StringPrintf("an rosalloc size bracket %d lock", static_cast<int>(i));
82    size_bracket_locks_[i] = new Mutex(size_bracket_lock_names_[i].c_str(), kRosAllocBracketLock);
83    current_runs_[i] = dedicated_full_run_;
84  }
85  DCHECK_EQ(footprint_, capacity_);
86  size_t num_of_pages = footprint_ / kPageSize;
87  size_t max_num_of_pages = max_capacity_ / kPageSize;
88  std::string error_msg;
89  page_map_mem_map_.reset(MemMap::MapAnonymous("rosalloc page map", nullptr,
90                                               RoundUp(max_num_of_pages, kPageSize),
91                                               PROT_READ | PROT_WRITE, false, false, &error_msg));
92  CHECK(page_map_mem_map_.get() != nullptr) << "Couldn't allocate the page map : " << error_msg;
93  page_map_ = page_map_mem_map_->Begin();
94  page_map_size_ = num_of_pages;
95  max_page_map_size_ = max_num_of_pages;
96  free_page_run_size_map_.resize(num_of_pages);
97  FreePageRun* free_pages = reinterpret_cast<FreePageRun*>(base_);
98  if (kIsDebugBuild) {
99    free_pages->magic_num_ = kMagicNumFree;
100  }
101  free_pages->SetByteSize(this, capacity_);
102  DCHECK_EQ(capacity_ % kPageSize, static_cast<size_t>(0));
103  DCHECK(free_pages->IsFree());
104  free_pages->ReleasePages(this);
105  DCHECK(free_pages->IsFree());
106  free_page_runs_.insert(free_pages);
107  if (kTraceRosAlloc) {
108    LOG(INFO) << "RosAlloc::RosAlloc() : Inserted run 0x" << std::hex
109              << reinterpret_cast<intptr_t>(free_pages)
110              << " into free_page_runs_";
111  }
112}
113
114RosAlloc::~RosAlloc() {
115  for (size_t i = 0; i < kNumOfSizeBrackets; i++) {
116    delete size_bracket_locks_[i];
117  }
118  if (is_running_on_memory_tool_) {
119    MEMORY_TOOL_MAKE_DEFINED(base_, capacity_);
120  }
121}
122
123void* RosAlloc::AllocPages(Thread* self, size_t num_pages, uint8_t page_map_type) {
124  lock_.AssertHeld(self);
125  DCHECK(page_map_type == kPageMapRun || page_map_type == kPageMapLargeObject);
126  FreePageRun* res = nullptr;
127  const size_t req_byte_size = num_pages * kPageSize;
128  // Find the lowest address free page run that's large enough.
129  for (auto it = free_page_runs_.begin(); it != free_page_runs_.end(); ) {
130    FreePageRun* fpr = *it;
131    DCHECK(fpr->IsFree());
132    size_t fpr_byte_size = fpr->ByteSize(this);
133    DCHECK_EQ(fpr_byte_size % kPageSize, static_cast<size_t>(0));
134    if (req_byte_size <= fpr_byte_size) {
135      // Found one.
136      free_page_runs_.erase(it++);
137      if (kTraceRosAlloc) {
138        LOG(INFO) << "RosAlloc::AllocPages() : Erased run 0x"
139                  << std::hex << reinterpret_cast<intptr_t>(fpr)
140                  << " from free_page_runs_";
141      }
142      if (req_byte_size < fpr_byte_size) {
143        // Split.
144        FreePageRun* remainder = reinterpret_cast<FreePageRun*>(reinterpret_cast<uint8_t*>(fpr) + req_byte_size);
145        if (kIsDebugBuild) {
146          remainder->magic_num_ = kMagicNumFree;
147        }
148        remainder->SetByteSize(this, fpr_byte_size - req_byte_size);
149        DCHECK_EQ(remainder->ByteSize(this) % kPageSize, static_cast<size_t>(0));
150        // Don't need to call madvise on remainder here.
151        free_page_runs_.insert(remainder);
152        if (kTraceRosAlloc) {
153          LOG(INFO) << "RosAlloc::AllocPages() : Inserted run 0x" << std::hex
154                    << reinterpret_cast<intptr_t>(remainder)
155                    << " into free_page_runs_";
156        }
157        fpr->SetByteSize(this, req_byte_size);
158        DCHECK_EQ(fpr->ByteSize(this) % kPageSize, static_cast<size_t>(0));
159      }
160      res = fpr;
161      break;
162    } else {
163      ++it;
164    }
165  }
166
167  // Failed to allocate pages. Grow the footprint, if possible.
168  if (UNLIKELY(res == nullptr && capacity_ > footprint_)) {
169    FreePageRun* last_free_page_run = nullptr;
170    size_t last_free_page_run_size;
171    auto it = free_page_runs_.rbegin();
172    if (it != free_page_runs_.rend() && (last_free_page_run = *it)->End(this) == base_ + footprint_) {
173      // There is a free page run at the end.
174      DCHECK(last_free_page_run->IsFree());
175      DCHECK(IsFreePage(ToPageMapIndex(last_free_page_run)));
176      last_free_page_run_size = last_free_page_run->ByteSize(this);
177    } else {
178      // There is no free page run at the end.
179      last_free_page_run_size = 0;
180    }
181    DCHECK_LT(last_free_page_run_size, req_byte_size);
182    if (capacity_ - footprint_ + last_free_page_run_size >= req_byte_size) {
183      // If we grow the heap, we can allocate it.
184      size_t increment = std::min(std::max(2 * MB, req_byte_size - last_free_page_run_size),
185                                  capacity_ - footprint_);
186      DCHECK_EQ(increment % kPageSize, static_cast<size_t>(0));
187      size_t new_footprint = footprint_ + increment;
188      size_t new_num_of_pages = new_footprint / kPageSize;
189      DCHECK_LT(page_map_size_, new_num_of_pages);
190      DCHECK_LT(free_page_run_size_map_.size(), new_num_of_pages);
191      page_map_size_ = new_num_of_pages;
192      DCHECK_LE(page_map_size_, max_page_map_size_);
193      free_page_run_size_map_.resize(new_num_of_pages);
194      ArtRosAllocMoreCore(this, increment);
195      if (last_free_page_run_size > 0) {
196        // There was a free page run at the end. Expand its size.
197        DCHECK_EQ(last_free_page_run_size, last_free_page_run->ByteSize(this));
198        last_free_page_run->SetByteSize(this, last_free_page_run_size + increment);
199        DCHECK_EQ(last_free_page_run->ByteSize(this) % kPageSize, static_cast<size_t>(0));
200        DCHECK_EQ(last_free_page_run->End(this), base_ + new_footprint);
201      } else {
202        // Otherwise, insert a new free page run at the end.
203        FreePageRun* new_free_page_run = reinterpret_cast<FreePageRun*>(base_ + footprint_);
204        if (kIsDebugBuild) {
205          new_free_page_run->magic_num_ = kMagicNumFree;
206        }
207        new_free_page_run->SetByteSize(this, increment);
208        DCHECK_EQ(new_free_page_run->ByteSize(this) % kPageSize, static_cast<size_t>(0));
209        free_page_runs_.insert(new_free_page_run);
210        DCHECK_EQ(*free_page_runs_.rbegin(), new_free_page_run);
211        if (kTraceRosAlloc) {
212          LOG(INFO) << "RosAlloc::AlloPages() : Grew the heap by inserting run 0x"
213                    << std::hex << reinterpret_cast<intptr_t>(new_free_page_run)
214                    << " into free_page_runs_";
215        }
216      }
217      DCHECK_LE(footprint_ + increment, capacity_);
218      if (kTraceRosAlloc) {
219        LOG(INFO) << "RosAlloc::AllocPages() : increased the footprint from "
220                  << footprint_ << " to " << new_footprint;
221      }
222      footprint_ = new_footprint;
223
224      // And retry the last free page run.
225      it = free_page_runs_.rbegin();
226      DCHECK(it != free_page_runs_.rend());
227      FreePageRun* fpr = *it;
228      if (kIsDebugBuild && last_free_page_run_size > 0) {
229        DCHECK(last_free_page_run != nullptr);
230        DCHECK_EQ(last_free_page_run, fpr);
231      }
232      size_t fpr_byte_size = fpr->ByteSize(this);
233      DCHECK_EQ(fpr_byte_size % kPageSize, static_cast<size_t>(0));
234      DCHECK_LE(req_byte_size, fpr_byte_size);
235      free_page_runs_.erase(fpr);
236      if (kTraceRosAlloc) {
237        LOG(INFO) << "RosAlloc::AllocPages() : Erased run 0x" << std::hex << reinterpret_cast<intptr_t>(fpr)
238                  << " from free_page_runs_";
239      }
240      if (req_byte_size < fpr_byte_size) {
241        // Split if there's a remainder.
242        FreePageRun* remainder = reinterpret_cast<FreePageRun*>(reinterpret_cast<uint8_t*>(fpr) + req_byte_size);
243        if (kIsDebugBuild) {
244          remainder->magic_num_ = kMagicNumFree;
245        }
246        remainder->SetByteSize(this, fpr_byte_size - req_byte_size);
247        DCHECK_EQ(remainder->ByteSize(this) % kPageSize, static_cast<size_t>(0));
248        free_page_runs_.insert(remainder);
249        if (kTraceRosAlloc) {
250          LOG(INFO) << "RosAlloc::AllocPages() : Inserted run 0x" << std::hex
251                    << reinterpret_cast<intptr_t>(remainder)
252                    << " into free_page_runs_";
253        }
254        fpr->SetByteSize(this, req_byte_size);
255        DCHECK_EQ(fpr->ByteSize(this) % kPageSize, static_cast<size_t>(0));
256      }
257      res = fpr;
258    }
259  }
260  if (LIKELY(res != nullptr)) {
261    // Update the page map.
262    size_t page_map_idx = ToPageMapIndex(res);
263    for (size_t i = 0; i < num_pages; i++) {
264      DCHECK(IsFreePage(page_map_idx + i));
265    }
266    switch (page_map_type) {
267    case kPageMapRun:
268      page_map_[page_map_idx] = kPageMapRun;
269      for (size_t i = 1; i < num_pages; i++) {
270        page_map_[page_map_idx + i] = kPageMapRunPart;
271      }
272      break;
273    case kPageMapLargeObject:
274      page_map_[page_map_idx] = kPageMapLargeObject;
275      for (size_t i = 1; i < num_pages; i++) {
276        page_map_[page_map_idx + i] = kPageMapLargeObjectPart;
277      }
278      break;
279    default:
280      LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(page_map_type);
281      break;
282    }
283    if (kIsDebugBuild) {
284      // Clear the first page since it is not madvised due to the magic number.
285      memset(res, 0, kPageSize);
286    }
287    if (kTraceRosAlloc) {
288      LOG(INFO) << "RosAlloc::AllocPages() : 0x" << std::hex << reinterpret_cast<intptr_t>(res)
289                << "-0x" << (reinterpret_cast<intptr_t>(res) + num_pages * kPageSize)
290                << "(" << std::dec << (num_pages * kPageSize) << ")";
291    }
292    return res;
293  }
294
295  // Fail.
296  if (kTraceRosAlloc) {
297    LOG(INFO) << "RosAlloc::AllocPages() : nullptr";
298  }
299  return nullptr;
300}
301
302size_t RosAlloc::FreePages(Thread* self, void* ptr, bool already_zero) {
303  lock_.AssertHeld(self);
304  size_t pm_idx = ToPageMapIndex(ptr);
305  DCHECK_LT(pm_idx, page_map_size_);
306  uint8_t pm_type = page_map_[pm_idx];
307  DCHECK(pm_type == kPageMapRun || pm_type == kPageMapLargeObject);
308  uint8_t pm_part_type;
309  switch (pm_type) {
310  case kPageMapRun:
311    pm_part_type = kPageMapRunPart;
312    break;
313  case kPageMapLargeObject:
314    pm_part_type = kPageMapLargeObjectPart;
315    break;
316  default:
317    LOG(FATAL) << "Unreachable - " << __PRETTY_FUNCTION__ << " : " << "pm_idx=" << pm_idx << ", pm_type="
318               << static_cast<int>(pm_type) << ", ptr=" << std::hex
319               << reinterpret_cast<intptr_t>(ptr);
320    return 0;
321  }
322  // Update the page map and count the number of pages.
323  size_t num_pages = 1;
324  page_map_[pm_idx] = kPageMapEmpty;
325  size_t idx = pm_idx + 1;
326  size_t end = page_map_size_;
327  while (idx < end && page_map_[idx] == pm_part_type) {
328    page_map_[idx] = kPageMapEmpty;
329    num_pages++;
330    idx++;
331  }
332  const size_t byte_size = num_pages * kPageSize;
333  if (already_zero) {
334    if (ShouldCheckZeroMemory()) {
335      const uintptr_t* word_ptr = reinterpret_cast<uintptr_t*>(ptr);
336      for (size_t i = 0; i < byte_size / sizeof(uintptr_t); ++i) {
337        CHECK_EQ(word_ptr[i], 0U) << "words don't match at index " << i;
338      }
339    }
340  } else if (!DoesReleaseAllPages()) {
341    memset(ptr, 0, byte_size);
342  }
343
344  if (kTraceRosAlloc) {
345    LOG(INFO) << __PRETTY_FUNCTION__ << " : 0x" << std::hex << reinterpret_cast<intptr_t>(ptr)
346              << "-0x" << (reinterpret_cast<intptr_t>(ptr) + byte_size)
347              << "(" << std::dec << (num_pages * kPageSize) << ")";
348  }
349
350  // Turn it into a free run.
351  FreePageRun* fpr = reinterpret_cast<FreePageRun*>(ptr);
352  if (kIsDebugBuild) {
353    fpr->magic_num_ = kMagicNumFree;
354  }
355  fpr->SetByteSize(this, byte_size);
356  DCHECK_ALIGNED(fpr->ByteSize(this), kPageSize);
357
358  DCHECK(free_page_runs_.find(fpr) == free_page_runs_.end());
359  if (!free_page_runs_.empty()) {
360    // Try to coalesce in the higher address direction.
361    if (kTraceRosAlloc) {
362      LOG(INFO) << __PRETTY_FUNCTION__ << "RosAlloc::FreePages() : trying to coalesce a free page run 0x"
363                << std::hex << reinterpret_cast<uintptr_t>(fpr) << " [" << std::dec << pm_idx << "] -0x"
364                << std::hex << reinterpret_cast<uintptr_t>(fpr->End(this)) << " [" << std::dec
365                << (fpr->End(this) == End() ? page_map_size_ : ToPageMapIndex(fpr->End(this))) << "]";
366    }
367    auto higher_it = free_page_runs_.upper_bound(fpr);
368    if (higher_it != free_page_runs_.end()) {
369      for (auto it = higher_it; it != free_page_runs_.end(); ) {
370        FreePageRun* h = *it;
371        DCHECK_EQ(h->ByteSize(this) % kPageSize, static_cast<size_t>(0));
372        if (kTraceRosAlloc) {
373          LOG(INFO) << "RosAlloc::FreePages() : trying to coalesce with a higher free page run 0x"
374                    << std::hex << reinterpret_cast<uintptr_t>(h) << " [" << std::dec << ToPageMapIndex(h) << "] -0x"
375                    << std::hex << reinterpret_cast<uintptr_t>(h->End(this)) << " [" << std::dec
376                    << (h->End(this) == End() ? page_map_size_ : ToPageMapIndex(h->End(this))) << "]";
377        }
378        if (fpr->End(this) == h->Begin()) {
379          if (kTraceRosAlloc) {
380            LOG(INFO) << "Success";
381          }
382          // Clear magic num since this is no longer the start of a free page run.
383          if (kIsDebugBuild) {
384            h->magic_num_ = 0;
385          }
386          free_page_runs_.erase(it++);
387          if (kTraceRosAlloc) {
388            LOG(INFO) << "RosAlloc::FreePages() : (coalesce) Erased run 0x" << std::hex
389                      << reinterpret_cast<intptr_t>(h)
390                      << " from free_page_runs_";
391          }
392          fpr->SetByteSize(this, fpr->ByteSize(this) + h->ByteSize(this));
393          DCHECK_EQ(fpr->ByteSize(this) % kPageSize, static_cast<size_t>(0));
394        } else {
395          // Not adjacent. Stop.
396          if (kTraceRosAlloc) {
397            LOG(INFO) << "Fail";
398          }
399          break;
400        }
401      }
402    }
403    // Try to coalesce in the lower address direction.
404    auto lower_it = free_page_runs_.upper_bound(fpr);
405    if (lower_it != free_page_runs_.begin()) {
406      --lower_it;
407      for (auto it = lower_it; ; ) {
408        // We want to try to coalesce with the first element but
409        // there's no "<=" operator for the iterator.
410        bool to_exit_loop = it == free_page_runs_.begin();
411
412        FreePageRun* l = *it;
413        DCHECK_EQ(l->ByteSize(this) % kPageSize, static_cast<size_t>(0));
414        if (kTraceRosAlloc) {
415          LOG(INFO) << "RosAlloc::FreePages() : trying to coalesce with a lower free page run 0x"
416                    << std::hex << reinterpret_cast<uintptr_t>(l) << " [" << std::dec << ToPageMapIndex(l) << "] -0x"
417                    << std::hex << reinterpret_cast<uintptr_t>(l->End(this)) << " [" << std::dec
418                    << (l->End(this) == End() ? page_map_size_ : ToPageMapIndex(l->End(this))) << "]";
419        }
420        if (l->End(this) == fpr->Begin()) {
421          if (kTraceRosAlloc) {
422            LOG(INFO) << "Success";
423          }
424          free_page_runs_.erase(it--);
425          if (kTraceRosAlloc) {
426            LOG(INFO) << "RosAlloc::FreePages() : (coalesce) Erased run 0x" << std::hex
427                      << reinterpret_cast<intptr_t>(l)
428                      << " from free_page_runs_";
429          }
430          l->SetByteSize(this, l->ByteSize(this) + fpr->ByteSize(this));
431          DCHECK_EQ(l->ByteSize(this) % kPageSize, static_cast<size_t>(0));
432          // Clear magic num since this is no longer the start of a free page run.
433          if (kIsDebugBuild) {
434            fpr->magic_num_ = 0;
435          }
436          fpr = l;
437        } else {
438          // Not adjacent. Stop.
439          if (kTraceRosAlloc) {
440            LOG(INFO) << "Fail";
441          }
442          break;
443        }
444        if (to_exit_loop) {
445          break;
446        }
447      }
448    }
449  }
450
451  // Insert it.
452  DCHECK_EQ(fpr->ByteSize(this) % kPageSize, static_cast<size_t>(0));
453  DCHECK(free_page_runs_.find(fpr) == free_page_runs_.end());
454  DCHECK(fpr->IsFree());
455  fpr->ReleasePages(this);
456  DCHECK(fpr->IsFree());
457  free_page_runs_.insert(fpr);
458  DCHECK(free_page_runs_.find(fpr) != free_page_runs_.end());
459  if (kTraceRosAlloc) {
460    LOG(INFO) << "RosAlloc::FreePages() : Inserted run 0x" << std::hex << reinterpret_cast<intptr_t>(fpr)
461              << " into free_page_runs_";
462  }
463  return byte_size;
464}
465
466void* RosAlloc::AllocLargeObject(Thread* self, size_t size, size_t* bytes_allocated,
467                                 size_t* usable_size, size_t* bytes_tl_bulk_allocated) {
468  DCHECK(bytes_allocated != nullptr);
469  DCHECK(usable_size != nullptr);
470  DCHECK_GT(size, kLargeSizeThreshold);
471  size_t num_pages = RoundUp(size, kPageSize) / kPageSize;
472  void* r;
473  {
474    MutexLock mu(self, lock_);
475    r = AllocPages(self, num_pages, kPageMapLargeObject);
476  }
477  if (UNLIKELY(r == nullptr)) {
478    if (kTraceRosAlloc) {
479      LOG(INFO) << "RosAlloc::AllocLargeObject() : nullptr";
480    }
481    return nullptr;
482  }
483  const size_t total_bytes = num_pages * kPageSize;
484  *bytes_allocated = total_bytes;
485  *usable_size = total_bytes;
486  *bytes_tl_bulk_allocated = total_bytes;
487  if (kTraceRosAlloc) {
488    LOG(INFO) << "RosAlloc::AllocLargeObject() : 0x" << std::hex << reinterpret_cast<intptr_t>(r)
489              << "-0x" << (reinterpret_cast<intptr_t>(r) + num_pages * kPageSize)
490              << "(" << std::dec << (num_pages * kPageSize) << ")";
491  }
492  // Check if the returned memory is really all zero.
493  if (ShouldCheckZeroMemory()) {
494    CHECK_EQ(total_bytes % sizeof(uintptr_t), 0U);
495    const uintptr_t* words = reinterpret_cast<uintptr_t*>(r);
496    for (size_t i = 0; i < total_bytes / sizeof(uintptr_t); ++i) {
497      CHECK_EQ(words[i], 0U);
498    }
499  }
500  return r;
501}
502
503size_t RosAlloc::FreeInternal(Thread* self, void* ptr) {
504  DCHECK_LE(base_, ptr);
505  DCHECK_LT(ptr, base_ + footprint_);
506  size_t pm_idx = RoundDownToPageMapIndex(ptr);
507  Run* run = nullptr;
508  {
509    MutexLock mu(self, lock_);
510    DCHECK_LT(pm_idx, page_map_size_);
511    uint8_t page_map_entry = page_map_[pm_idx];
512    if (kTraceRosAlloc) {
513      LOG(INFO) << "RosAlloc::FreeInternal() : " << std::hex << ptr << ", pm_idx=" << std::dec << pm_idx
514                << ", page_map_entry=" << static_cast<int>(page_map_entry);
515    }
516    switch (page_map_[pm_idx]) {
517      case kPageMapLargeObject:
518        return FreePages(self, ptr, false);
519      case kPageMapLargeObjectPart:
520        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(page_map_[pm_idx]);
521        return 0;
522      case kPageMapRunPart: {
523        // Find the beginning of the run.
524        do {
525          --pm_idx;
526          DCHECK_LT(pm_idx, capacity_ / kPageSize);
527        } while (page_map_[pm_idx] != kPageMapRun);
528        FALLTHROUGH_INTENDED;
529      case kPageMapRun:
530        run = reinterpret_cast<Run*>(base_ + pm_idx * kPageSize);
531        DCHECK_EQ(run->magic_num_, kMagicNum);
532        break;
533      case kPageMapReleased:
534      case kPageMapEmpty:
535        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(page_map_[pm_idx]);
536        return 0;
537      }
538      default:
539        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(page_map_[pm_idx]);
540        return 0;
541    }
542  }
543  DCHECK(run != nullptr);
544  return FreeFromRun(self, ptr, run);
545}
546
547size_t RosAlloc::Free(Thread* self, void* ptr) {
548  ReaderMutexLock rmu(self, bulk_free_lock_);
549  return FreeInternal(self, ptr);
550}
551
552RosAlloc::Run* RosAlloc::AllocRun(Thread* self, size_t idx) {
553  RosAlloc::Run* new_run = nullptr;
554  {
555    MutexLock mu(self, lock_);
556    new_run = reinterpret_cast<Run*>(AllocPages(self, numOfPages[idx], kPageMapRun));
557  }
558  if (LIKELY(new_run != nullptr)) {
559    if (kIsDebugBuild) {
560      new_run->magic_num_ = kMagicNum;
561    }
562    new_run->size_bracket_idx_ = idx;
563    DCHECK(!new_run->IsThreadLocal());
564    DCHECK(!new_run->to_be_bulk_freed_);
565    if (kUsePrefetchDuringAllocRun && idx < kNumThreadLocalSizeBrackets) {
566      // Take ownership of the cache lines if we are likely to be thread local run.
567      if (kPrefetchNewRunDataByZeroing) {
568        // Zeroing the data is sometimes faster than prefetching but it increases memory usage
569        // since we end up dirtying zero pages which may have been madvised.
570        new_run->ZeroData();
571      } else {
572        const size_t num_of_slots = numOfSlots[idx];
573        const size_t bracket_size = bracketSizes[idx];
574        const size_t num_of_bytes = num_of_slots * bracket_size;
575        uint8_t* begin = reinterpret_cast<uint8_t*>(new_run) + headerSizes[idx];
576        for (size_t i = 0; i < num_of_bytes; i += kPrefetchStride) {
577          __builtin_prefetch(begin + i);
578        }
579      }
580    }
581    new_run->InitFreeList();
582  }
583  return new_run;
584}
585
586RosAlloc::Run* RosAlloc::RefillRun(Thread* self, size_t idx) {
587  // Get the lowest address non-full run from the binary tree.
588  auto* const bt = &non_full_runs_[idx];
589  if (!bt->empty()) {
590    // If there's one, use it as the current run.
591    auto it = bt->begin();
592    Run* non_full_run = *it;
593    DCHECK(non_full_run != nullptr);
594    DCHECK(!non_full_run->IsThreadLocal());
595    bt->erase(it);
596    return non_full_run;
597  }
598  // If there's none, allocate a new run and use it as the current run.
599  return AllocRun(self, idx);
600}
601
602inline void* RosAlloc::AllocFromCurrentRunUnlocked(Thread* self, size_t idx) {
603  Run* current_run = current_runs_[idx];
604  DCHECK(current_run != nullptr);
605  void* slot_addr = current_run->AllocSlot();
606  if (UNLIKELY(slot_addr == nullptr)) {
607    // The current run got full. Try to refill it.
608    DCHECK(current_run->IsFull());
609    if (kIsDebugBuild && current_run != dedicated_full_run_) {
610      full_runs_[idx].insert(current_run);
611      if (kTraceRosAlloc) {
612        LOG(INFO) << __PRETTY_FUNCTION__ << " : Inserted run 0x" << std::hex
613                  << reinterpret_cast<intptr_t>(current_run)
614                  << " into full_runs_[" << std::dec << idx << "]";
615      }
616      DCHECK(non_full_runs_[idx].find(current_run) == non_full_runs_[idx].end());
617      DCHECK(full_runs_[idx].find(current_run) != full_runs_[idx].end());
618    }
619    current_run = RefillRun(self, idx);
620    if (UNLIKELY(current_run == nullptr)) {
621      // Failed to allocate a new run, make sure that it is the dedicated full run.
622      current_runs_[idx] = dedicated_full_run_;
623      return nullptr;
624    }
625    DCHECK(current_run != nullptr);
626    DCHECK(non_full_runs_[idx].find(current_run) == non_full_runs_[idx].end());
627    DCHECK(full_runs_[idx].find(current_run) == full_runs_[idx].end());
628    current_run->SetIsThreadLocal(false);
629    current_runs_[idx] = current_run;
630    DCHECK(!current_run->IsFull());
631    slot_addr = current_run->AllocSlot();
632    // Must succeed now with a new run.
633    DCHECK(slot_addr != nullptr);
634  }
635  return slot_addr;
636}
637
638void* RosAlloc::AllocFromRunThreadUnsafe(Thread* self, size_t size, size_t* bytes_allocated,
639                                         size_t* usable_size,
640                                         size_t* bytes_tl_bulk_allocated) {
641  DCHECK(bytes_allocated != nullptr);
642  DCHECK(usable_size != nullptr);
643  DCHECK(bytes_tl_bulk_allocated != nullptr);
644  DCHECK_LE(size, kLargeSizeThreshold);
645  size_t bracket_size;
646  size_t idx = SizeToIndexAndBracketSize(size, &bracket_size);
647  Locks::mutator_lock_->AssertExclusiveHeld(self);
648  void* slot_addr = AllocFromCurrentRunUnlocked(self, idx);
649  if (LIKELY(slot_addr != nullptr)) {
650    *bytes_allocated = bracket_size;
651    *usable_size = bracket_size;
652    *bytes_tl_bulk_allocated = bracket_size;
653  }
654  // Caller verifies that it is all 0.
655  return slot_addr;
656}
657
658void* RosAlloc::AllocFromRun(Thread* self, size_t size, size_t* bytes_allocated,
659                             size_t* usable_size, size_t* bytes_tl_bulk_allocated) {
660  DCHECK(bytes_allocated != nullptr);
661  DCHECK(usable_size != nullptr);
662  DCHECK(bytes_tl_bulk_allocated != nullptr);
663  DCHECK_LE(size, kLargeSizeThreshold);
664  size_t bracket_size;
665  size_t idx = SizeToIndexAndBracketSize(size, &bracket_size);
666  void* slot_addr;
667  if (LIKELY(idx < kNumThreadLocalSizeBrackets)) {
668    // Use a thread-local run.
669    Run* thread_local_run = reinterpret_cast<Run*>(self->GetRosAllocRun(idx));
670    // Allow invalid since this will always fail the allocation.
671    if (kIsDebugBuild) {
672      // Need the lock to prevent race conditions.
673      MutexLock mu(self, *size_bracket_locks_[idx]);
674      CHECK(non_full_runs_[idx].find(thread_local_run) == non_full_runs_[idx].end());
675      CHECK(full_runs_[idx].find(thread_local_run) == full_runs_[idx].end());
676    }
677    DCHECK(thread_local_run != nullptr);
678    DCHECK(thread_local_run->IsThreadLocal() || thread_local_run == dedicated_full_run_);
679    slot_addr = thread_local_run->AllocSlot();
680    // The allocation must fail if the run is invalid.
681    DCHECK(thread_local_run != dedicated_full_run_ || slot_addr == nullptr)
682        << "allocated from an invalid run";
683    if (UNLIKELY(slot_addr == nullptr)) {
684      // The run got full. Try to free slots.
685      DCHECK(thread_local_run->IsFull());
686      MutexLock mu(self, *size_bracket_locks_[idx]);
687      bool is_all_free_after_merge;
688      // This is safe to do for the dedicated_full_run_ since the bitmaps are empty.
689      if (thread_local_run->MergeThreadLocalFreeListToFreeList(&is_all_free_after_merge)) {
690        DCHECK_NE(thread_local_run, dedicated_full_run_);
691        // Some slot got freed. Keep it.
692        DCHECK(!thread_local_run->IsFull());
693        DCHECK_EQ(is_all_free_after_merge, thread_local_run->IsAllFree());
694      } else {
695        // No slots got freed. Try to refill the thread-local run.
696        DCHECK(thread_local_run->IsFull());
697        if (thread_local_run != dedicated_full_run_) {
698          thread_local_run->SetIsThreadLocal(false);
699          if (kIsDebugBuild) {
700            full_runs_[idx].insert(thread_local_run);
701            if (kTraceRosAlloc) {
702              LOG(INFO) << "RosAlloc::AllocFromRun() : Inserted run 0x" << std::hex
703                        << reinterpret_cast<intptr_t>(thread_local_run)
704                        << " into full_runs_[" << std::dec << idx << "]";
705            }
706          }
707          DCHECK(non_full_runs_[idx].find(thread_local_run) == non_full_runs_[idx].end());
708          DCHECK(full_runs_[idx].find(thread_local_run) != full_runs_[idx].end());
709        }
710
711        thread_local_run = RefillRun(self, idx);
712        if (UNLIKELY(thread_local_run == nullptr)) {
713          self->SetRosAllocRun(idx, dedicated_full_run_);
714          return nullptr;
715        }
716        DCHECK(non_full_runs_[idx].find(thread_local_run) == non_full_runs_[idx].end());
717        DCHECK(full_runs_[idx].find(thread_local_run) == full_runs_[idx].end());
718        thread_local_run->SetIsThreadLocal(true);
719        self->SetRosAllocRun(idx, thread_local_run);
720        DCHECK(!thread_local_run->IsFull());
721      }
722      DCHECK(thread_local_run != nullptr);
723      DCHECK(!thread_local_run->IsFull());
724      DCHECK(thread_local_run->IsThreadLocal());
725      // Account for all the free slots in the new or refreshed thread local run.
726      *bytes_tl_bulk_allocated = thread_local_run->NumberOfFreeSlots() * bracket_size;
727      slot_addr = thread_local_run->AllocSlot();
728      // Must succeed now with a new run.
729      DCHECK(slot_addr != nullptr);
730    } else {
731      // The slot is already counted. Leave it as is.
732      *bytes_tl_bulk_allocated = 0;
733    }
734    DCHECK(slot_addr != nullptr);
735    if (kTraceRosAlloc) {
736      LOG(INFO) << "RosAlloc::AllocFromRun() thread-local : 0x" << std::hex
737                << reinterpret_cast<intptr_t>(slot_addr)
738                << "-0x" << (reinterpret_cast<intptr_t>(slot_addr) + bracket_size)
739                << "(" << std::dec << (bracket_size) << ")";
740    }
741    *bytes_allocated = bracket_size;
742    *usable_size = bracket_size;
743  } else {
744    // Use the (shared) current run.
745    MutexLock mu(self, *size_bracket_locks_[idx]);
746    slot_addr = AllocFromCurrentRunUnlocked(self, idx);
747    if (kTraceRosAlloc) {
748      LOG(INFO) << "RosAlloc::AllocFromRun() : 0x" << std::hex
749                << reinterpret_cast<intptr_t>(slot_addr)
750                << "-0x" << (reinterpret_cast<intptr_t>(slot_addr) + bracket_size)
751                << "(" << std::dec << (bracket_size) << ")";
752    }
753    if (LIKELY(slot_addr != nullptr)) {
754      *bytes_allocated = bracket_size;
755      *usable_size = bracket_size;
756      *bytes_tl_bulk_allocated = bracket_size;
757    }
758  }
759  // Caller verifies that it is all 0.
760  return slot_addr;
761}
762
763size_t RosAlloc::FreeFromRun(Thread* self, void* ptr, Run* run) {
764  DCHECK_EQ(run->magic_num_, kMagicNum);
765  DCHECK_LT(run, ptr);
766  DCHECK_LT(ptr, run->End());
767  const size_t idx = run->size_bracket_idx_;
768  const size_t bracket_size = bracketSizes[idx];
769  bool run_was_full = false;
770  MutexLock brackets_mu(self, *size_bracket_locks_[idx]);
771  if (kIsDebugBuild) {
772    run_was_full = run->IsFull();
773  }
774  if (kTraceRosAlloc) {
775    LOG(INFO) << "RosAlloc::FreeFromRun() : 0x" << std::hex << reinterpret_cast<intptr_t>(ptr);
776  }
777  if (LIKELY(run->IsThreadLocal())) {
778    // It's a thread-local run. Just mark the thread-local free bit map and return.
779    DCHECK_LT(run->size_bracket_idx_, kNumThreadLocalSizeBrackets);
780    DCHECK(non_full_runs_[idx].find(run) == non_full_runs_[idx].end());
781    DCHECK(full_runs_[idx].find(run) == full_runs_[idx].end());
782    run->AddToThreadLocalFreeList(ptr);
783    if (kTraceRosAlloc) {
784      LOG(INFO) << "RosAlloc::FreeFromRun() : Freed a slot in a thread local run 0x" << std::hex
785                << reinterpret_cast<intptr_t>(run);
786    }
787    // A thread local run will be kept as a thread local even if it's become all free.
788    return bracket_size;
789  }
790  // Free the slot in the run.
791  run->FreeSlot(ptr);
792  auto* non_full_runs = &non_full_runs_[idx];
793  if (run->IsAllFree()) {
794    // It has just become completely free. Free the pages of this run.
795    std::set<Run*>::iterator pos = non_full_runs->find(run);
796    if (pos != non_full_runs->end()) {
797      non_full_runs->erase(pos);
798      if (kTraceRosAlloc) {
799        LOG(INFO) << "RosAlloc::FreeFromRun() : Erased run 0x" << std::hex
800                  << reinterpret_cast<intptr_t>(run) << " from non_full_runs_";
801      }
802    }
803    if (run == current_runs_[idx]) {
804      current_runs_[idx] = dedicated_full_run_;
805    }
806    DCHECK(non_full_runs_[idx].find(run) == non_full_runs_[idx].end());
807    DCHECK(full_runs_[idx].find(run) == full_runs_[idx].end());
808    run->ZeroHeaderAndSlotHeaders();
809    {
810      MutexLock lock_mu(self, lock_);
811      FreePages(self, run, true);
812    }
813  } else {
814    // It is not completely free. If it wasn't the current run or
815    // already in the non-full run set (i.e., it was full) insert it
816    // into the non-full run set.
817    if (run != current_runs_[idx]) {
818      auto* full_runs = kIsDebugBuild ? &full_runs_[idx] : nullptr;
819      auto pos = non_full_runs->find(run);
820      if (pos == non_full_runs->end()) {
821        DCHECK(run_was_full);
822        DCHECK(full_runs->find(run) != full_runs->end());
823        if (kIsDebugBuild) {
824          full_runs->erase(run);
825          if (kTraceRosAlloc) {
826            LOG(INFO) << "RosAlloc::FreeFromRun() : Erased run 0x" << std::hex
827                      << reinterpret_cast<intptr_t>(run) << " from full_runs_";
828          }
829        }
830        non_full_runs->insert(run);
831        DCHECK(!run->IsFull());
832        if (kTraceRosAlloc) {
833          LOG(INFO) << "RosAlloc::FreeFromRun() : Inserted run 0x" << std::hex
834                    << reinterpret_cast<intptr_t>(run)
835                    << " into non_full_runs_[" << std::dec << idx << "]";
836        }
837      }
838    }
839  }
840  return bracket_size;
841}
842
843template<bool kUseTail>
844std::string RosAlloc::Run::FreeListToStr(SlotFreeList<kUseTail>* free_list) {
845  std::string free_list_str;
846  const uint8_t idx = size_bracket_idx_;
847  const size_t bracket_size = bracketSizes[idx];
848  for (Slot* slot = free_list->Head(); slot != nullptr; slot = slot->Next()) {
849    bool is_last = slot->Next() == nullptr;
850    uintptr_t slot_offset = reinterpret_cast<uintptr_t>(slot) -
851        reinterpret_cast<uintptr_t>(FirstSlot());
852    DCHECK_EQ(slot_offset % bracket_size, 0U);
853    uintptr_t slot_idx = slot_offset / bracket_size;
854    if (!is_last) {
855      free_list_str.append(StringPrintf("%u-", static_cast<uint32_t>(slot_idx)));
856    } else {
857      free_list_str.append(StringPrintf("%u", static_cast<uint32_t>(slot_idx)));
858    }
859  }
860  return free_list_str;
861}
862
863std::string RosAlloc::Run::Dump() {
864  size_t idx = size_bracket_idx_;
865  std::ostringstream stream;
866  stream << "RosAlloc Run = " << reinterpret_cast<void*>(this)
867         << "{ magic_num=" << static_cast<int>(magic_num_)
868         << " size_bracket_idx=" << idx
869         << " is_thread_local=" << static_cast<int>(is_thread_local_)
870         << " to_be_bulk_freed=" << static_cast<int>(to_be_bulk_freed_)
871         << " free_list=" << FreeListToStr(&free_list_)
872         << " bulk_free_list=" << FreeListToStr(&bulk_free_list_)
873         << " thread_local_list=" << FreeListToStr(&thread_local_free_list_)
874         << " }" << std::endl;
875  return stream.str();
876}
877
878void RosAlloc::Run::FreeSlot(void* ptr) {
879  DCHECK(!IsThreadLocal());
880  const uint8_t idx = size_bracket_idx_;
881  const size_t bracket_size = bracketSizes[idx];
882  Slot* slot = ToSlot(ptr);
883  // Zero out the memory.
884  // TODO: Investigate alternate memset since ptr is guaranteed to be aligned to 16.
885  memset(slot, 0, bracket_size);
886  free_list_.Add(slot);
887  if (kTraceRosAlloc) {
888    LOG(INFO) << "RosAlloc::Run::FreeSlot() : " << slot
889              << ", bracket_size=" << std::dec << bracket_size << ", slot_idx=" << SlotIndex(slot);
890  }
891}
892
893inline bool RosAlloc::Run::MergeThreadLocalFreeListToFreeList(bool* is_all_free_after_out) {
894  DCHECK(IsThreadLocal());
895  // Merge the thread local free list into the free list and clear the thread local free list.
896  const uint8_t idx = size_bracket_idx_;
897  bool thread_local_free_list_size = thread_local_free_list_.Size();
898  const size_t size_before = free_list_.Size();
899  free_list_.Merge(&thread_local_free_list_);
900  const size_t size_after = free_list_.Size();
901  DCHECK_EQ(size_before < size_after, thread_local_free_list_size > 0);
902  DCHECK_LE(size_before, size_after);
903  *is_all_free_after_out = free_list_.Size() == numOfSlots[idx];
904  // Return true at least one slot was added to the free list.
905  return size_before < size_after;
906}
907
908inline void RosAlloc::Run::MergeBulkFreeListToFreeList() {
909  DCHECK(!IsThreadLocal());
910  // Merge the bulk free list into the free list and clear the bulk free list.
911  free_list_.Merge(&bulk_free_list_);
912}
913
914inline void RosAlloc::Run::MergeBulkFreeListToThreadLocalFreeList() {
915  DCHECK(IsThreadLocal());
916  // Merge the bulk free list into the thread local free list and clear the bulk free list.
917  thread_local_free_list_.Merge(&bulk_free_list_);
918}
919
920inline void RosAlloc::Run::AddToThreadLocalFreeList(void* ptr) {
921  DCHECK(IsThreadLocal());
922  AddToFreeListShared(ptr, &thread_local_free_list_, __FUNCTION__);
923}
924
925inline size_t RosAlloc::Run::AddToBulkFreeList(void* ptr) {
926  return AddToFreeListShared(ptr, &bulk_free_list_, __FUNCTION__);
927}
928
929inline size_t RosAlloc::Run::AddToFreeListShared(void* ptr,
930                                                 SlotFreeList<true>* free_list,
931                                                 const char* caller_name) {
932  const uint8_t idx = size_bracket_idx_;
933  const size_t bracket_size = bracketSizes[idx];
934  Slot* slot = ToSlot(ptr);
935  memset(slot, 0, bracket_size);
936  free_list->Add(slot);
937  if (kTraceRosAlloc) {
938    LOG(INFO) << "RosAlloc::Run::" << caller_name << "() : " << ptr
939              << ", bracket_size=" << std::dec << bracket_size << ", slot_idx=" << SlotIndex(slot);
940  }
941  return bracket_size;
942}
943
944inline void RosAlloc::Run::ZeroHeaderAndSlotHeaders() {
945  DCHECK(IsAllFree());
946  const uint8_t idx = size_bracket_idx_;
947  // Zero the slot header (next pointers).
948  for (Slot* slot = free_list_.Head(); slot != nullptr; ) {
949    Slot* next_slot = slot->Next();
950    slot->Clear();
951    slot = next_slot;
952  }
953  // Zero the header.
954  memset(this, 0, headerSizes[idx]);
955  // Check that the entire run is all zero.
956  if (kIsDebugBuild) {
957    const size_t size = numOfPages[idx] * kPageSize;
958    const uintptr_t* word_ptr = reinterpret_cast<uintptr_t*>(this);
959    for (size_t i = 0; i < size / sizeof(uintptr_t); ++i) {
960      CHECK_EQ(word_ptr[i], 0U) << "words don't match at index " << i;
961    }
962  }
963}
964
965inline void RosAlloc::Run::ZeroData() {
966  const uint8_t idx = size_bracket_idx_;
967  uint8_t* slot_begin = reinterpret_cast<uint8_t*>(FirstSlot());
968  memset(slot_begin, 0, numOfSlots[idx] * bracketSizes[idx]);
969}
970
971void RosAlloc::Run::InspectAllSlots(void (*handler)(void* start, void* end, size_t used_bytes, void* callback_arg),
972                                    void* arg) {
973  size_t idx = size_bracket_idx_;
974  uint8_t* slot_base = reinterpret_cast<uint8_t*>(this) + headerSizes[idx];
975  size_t num_slots = numOfSlots[idx];
976  size_t bracket_size = IndexToBracketSize(idx);
977  DCHECK_EQ(slot_base + num_slots * bracket_size,
978            reinterpret_cast<uint8_t*>(this) + numOfPages[idx] * kPageSize);
979  // Free slots are on the free list and the allocated/used slots are not. We traverse the free list
980  // to find out and record which slots are free in the is_free array.
981  std::unique_ptr<bool[]> is_free(new bool[num_slots]());  // zero initialized
982  for (Slot* slot = free_list_.Head(); slot != nullptr; slot = slot->Next()) {
983    size_t slot_idx = SlotIndex(slot);
984    DCHECK_LT(slot_idx, num_slots);
985    is_free[slot_idx] = true;
986  }
987  if (IsThreadLocal()) {
988    for (Slot* slot = thread_local_free_list_.Head(); slot != nullptr; slot = slot->Next()) {
989      size_t slot_idx = SlotIndex(slot);
990      DCHECK_LT(slot_idx, num_slots);
991      is_free[slot_idx] = true;
992    }
993  }
994  for (size_t slot_idx = 0; slot_idx < num_slots; ++slot_idx) {
995    uint8_t* slot_addr = slot_base + slot_idx * bracket_size;
996    if (!is_free[slot_idx]) {
997      handler(slot_addr, slot_addr + bracket_size, bracket_size, arg);
998    } else {
999      handler(slot_addr, slot_addr + bracket_size, 0, arg);
1000    }
1001  }
1002}
1003
1004// If true, read the page map entries in BulkFree() without using the
1005// lock for better performance, assuming that the existence of an
1006// allocated chunk/pointer being freed in BulkFree() guarantees that
1007// the page map entry won't change. Disabled for now.
1008static constexpr bool kReadPageMapEntryWithoutLockInBulkFree = true;
1009
1010size_t RosAlloc::BulkFree(Thread* self, void** ptrs, size_t num_ptrs) {
1011  size_t freed_bytes = 0;
1012  if ((false)) {
1013    // Used only to test Free() as GC uses only BulkFree().
1014    for (size_t i = 0; i < num_ptrs; ++i) {
1015      freed_bytes += FreeInternal(self, ptrs[i]);
1016    }
1017    return freed_bytes;
1018  }
1019
1020  WriterMutexLock wmu(self, bulk_free_lock_);
1021
1022  // First mark slots to free in the bulk free bit map without locking the
1023  // size bracket locks. On host, unordered_set is faster than vector + flag.
1024#ifdef __ANDROID__
1025  std::vector<Run*> runs;
1026#else
1027  std::unordered_set<Run*, hash_run, eq_run> runs;
1028#endif
1029  for (size_t i = 0; i < num_ptrs; i++) {
1030    void* ptr = ptrs[i];
1031    DCHECK_LE(base_, ptr);
1032    DCHECK_LT(ptr, base_ + footprint_);
1033    size_t pm_idx = RoundDownToPageMapIndex(ptr);
1034    Run* run = nullptr;
1035    if (kReadPageMapEntryWithoutLockInBulkFree) {
1036      // Read the page map entries without locking the lock.
1037      uint8_t page_map_entry = page_map_[pm_idx];
1038      if (kTraceRosAlloc) {
1039        LOG(INFO) << "RosAlloc::BulkFree() : " << std::hex << ptr << ", pm_idx="
1040                  << std::dec << pm_idx
1041                  << ", page_map_entry=" << static_cast<int>(page_map_entry);
1042      }
1043      if (LIKELY(page_map_entry == kPageMapRun)) {
1044        run = reinterpret_cast<Run*>(base_ + pm_idx * kPageSize);
1045      } else if (LIKELY(page_map_entry == kPageMapRunPart)) {
1046        size_t pi = pm_idx;
1047        // Find the beginning of the run.
1048        do {
1049          --pi;
1050          DCHECK_LT(pi, capacity_ / kPageSize);
1051        } while (page_map_[pi] != kPageMapRun);
1052        run = reinterpret_cast<Run*>(base_ + pi * kPageSize);
1053      } else if (page_map_entry == kPageMapLargeObject) {
1054        MutexLock mu(self, lock_);
1055        freed_bytes += FreePages(self, ptr, false);
1056        continue;
1057      } else {
1058        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(page_map_entry);
1059      }
1060    } else {
1061      // Read the page map entries with a lock.
1062      MutexLock mu(self, lock_);
1063      DCHECK_LT(pm_idx, page_map_size_);
1064      uint8_t page_map_entry = page_map_[pm_idx];
1065      if (kTraceRosAlloc) {
1066        LOG(INFO) << "RosAlloc::BulkFree() : " << std::hex << ptr << ", pm_idx="
1067                  << std::dec << pm_idx
1068                  << ", page_map_entry=" << static_cast<int>(page_map_entry);
1069      }
1070      if (LIKELY(page_map_entry == kPageMapRun)) {
1071        run = reinterpret_cast<Run*>(base_ + pm_idx * kPageSize);
1072      } else if (LIKELY(page_map_entry == kPageMapRunPart)) {
1073        size_t pi = pm_idx;
1074        // Find the beginning of the run.
1075        do {
1076          --pi;
1077          DCHECK_LT(pi, capacity_ / kPageSize);
1078        } while (page_map_[pi] != kPageMapRun);
1079        run = reinterpret_cast<Run*>(base_ + pi * kPageSize);
1080      } else if (page_map_entry == kPageMapLargeObject) {
1081        freed_bytes += FreePages(self, ptr, false);
1082        continue;
1083      } else {
1084        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(page_map_entry);
1085      }
1086    }
1087    DCHECK(run != nullptr);
1088    DCHECK_EQ(run->magic_num_, kMagicNum);
1089    // Set the bit in the bulk free bit map.
1090    freed_bytes += run->AddToBulkFreeList(ptr);
1091#ifdef __ANDROID__
1092    if (!run->to_be_bulk_freed_) {
1093      run->to_be_bulk_freed_ = true;
1094      runs.push_back(run);
1095    }
1096#else
1097    runs.insert(run);
1098#endif
1099  }
1100
1101  // Now, iterate over the affected runs and update the alloc bit map
1102  // based on the bulk free bit map (for non-thread-local runs) and
1103  // union the bulk free bit map into the thread-local free bit map
1104  // (for thread-local runs.)
1105  for (Run* run : runs) {
1106#ifdef __ANDROID__
1107    DCHECK(run->to_be_bulk_freed_);
1108    run->to_be_bulk_freed_ = false;
1109#endif
1110    size_t idx = run->size_bracket_idx_;
1111    MutexLock brackets_mu(self, *size_bracket_locks_[idx]);
1112    if (run->IsThreadLocal()) {
1113      DCHECK_LT(run->size_bracket_idx_, kNumThreadLocalSizeBrackets);
1114      DCHECK(non_full_runs_[idx].find(run) == non_full_runs_[idx].end());
1115      DCHECK(full_runs_[idx].find(run) == full_runs_[idx].end());
1116      run->MergeBulkFreeListToThreadLocalFreeList();
1117      if (kTraceRosAlloc) {
1118        LOG(INFO) << "RosAlloc::BulkFree() : Freed slot(s) in a thread local run 0x"
1119                  << std::hex << reinterpret_cast<intptr_t>(run);
1120      }
1121      DCHECK(run->IsThreadLocal());
1122      // A thread local run will be kept as a thread local even if
1123      // it's become all free.
1124    } else {
1125      bool run_was_full = run->IsFull();
1126      run->MergeBulkFreeListToFreeList();
1127      if (kTraceRosAlloc) {
1128        LOG(INFO) << "RosAlloc::BulkFree() : Freed slot(s) in a run 0x" << std::hex
1129                  << reinterpret_cast<intptr_t>(run);
1130      }
1131      // Check if the run should be moved to non_full_runs_ or
1132      // free_page_runs_.
1133      auto* non_full_runs = &non_full_runs_[idx];
1134      auto* full_runs = kIsDebugBuild ? &full_runs_[idx] : nullptr;
1135      if (run->IsAllFree()) {
1136        // It has just become completely free. Free the pages of the
1137        // run.
1138        bool run_was_current = run == current_runs_[idx];
1139        if (run_was_current) {
1140          DCHECK(full_runs->find(run) == full_runs->end());
1141          DCHECK(non_full_runs->find(run) == non_full_runs->end());
1142          // If it was a current run, reuse it.
1143        } else if (run_was_full) {
1144          // If it was full, remove it from the full run set (debug
1145          // only.)
1146          if (kIsDebugBuild) {
1147            std::unordered_set<Run*, hash_run, eq_run>::iterator pos = full_runs->find(run);
1148            DCHECK(pos != full_runs->end());
1149            full_runs->erase(pos);
1150            if (kTraceRosAlloc) {
1151              LOG(INFO) << "RosAlloc::BulkFree() : Erased run 0x" << std::hex
1152                        << reinterpret_cast<intptr_t>(run)
1153                        << " from full_runs_";
1154            }
1155            DCHECK(full_runs->find(run) == full_runs->end());
1156          }
1157        } else {
1158          // If it was in a non full run set, remove it from the set.
1159          DCHECK(full_runs->find(run) == full_runs->end());
1160          DCHECK(non_full_runs->find(run) != non_full_runs->end());
1161          non_full_runs->erase(run);
1162          if (kTraceRosAlloc) {
1163            LOG(INFO) << "RosAlloc::BulkFree() : Erased run 0x" << std::hex
1164                      << reinterpret_cast<intptr_t>(run)
1165                      << " from non_full_runs_";
1166          }
1167          DCHECK(non_full_runs->find(run) == non_full_runs->end());
1168        }
1169        if (!run_was_current) {
1170          run->ZeroHeaderAndSlotHeaders();
1171          MutexLock lock_mu(self, lock_);
1172          FreePages(self, run, true);
1173        }
1174      } else {
1175        // It is not completely free. If it wasn't the current run or
1176        // already in the non-full run set (i.e., it was full) insert
1177        // it into the non-full run set.
1178        if (run == current_runs_[idx]) {
1179          DCHECK(non_full_runs->find(run) == non_full_runs->end());
1180          DCHECK(full_runs->find(run) == full_runs->end());
1181          // If it was a current run, keep it.
1182        } else if (run_was_full) {
1183          // If it was full, remove it from the full run set (debug
1184          // only) and insert into the non-full run set.
1185          DCHECK(full_runs->find(run) != full_runs->end());
1186          DCHECK(non_full_runs->find(run) == non_full_runs->end());
1187          if (kIsDebugBuild) {
1188            full_runs->erase(run);
1189            if (kTraceRosAlloc) {
1190              LOG(INFO) << "RosAlloc::BulkFree() : Erased run 0x" << std::hex
1191                        << reinterpret_cast<intptr_t>(run)
1192                        << " from full_runs_";
1193            }
1194          }
1195          non_full_runs->insert(run);
1196          if (kTraceRosAlloc) {
1197            LOG(INFO) << "RosAlloc::BulkFree() : Inserted run 0x" << std::hex
1198                      << reinterpret_cast<intptr_t>(run)
1199                      << " into non_full_runs_[" << std::dec << idx;
1200          }
1201        } else {
1202          // If it was not full, so leave it in the non full run set.
1203          DCHECK(full_runs->find(run) == full_runs->end());
1204          DCHECK(non_full_runs->find(run) != non_full_runs->end());
1205        }
1206      }
1207    }
1208  }
1209  return freed_bytes;
1210}
1211
1212std::string RosAlloc::DumpPageMap() {
1213  std::ostringstream stream;
1214  stream << "RosAlloc PageMap: " << std::endl;
1215  lock_.AssertHeld(Thread::Current());
1216  size_t end = page_map_size_;
1217  FreePageRun* curr_fpr = nullptr;
1218  size_t curr_fpr_size = 0;
1219  size_t remaining_curr_fpr_size = 0;
1220  size_t num_running_empty_pages = 0;
1221  for (size_t i = 0; i < end; ++i) {
1222    uint8_t pm = page_map_[i];
1223    switch (pm) {
1224      case kPageMapReleased:
1225        // Fall-through.
1226      case kPageMapEmpty: {
1227        FreePageRun* fpr = reinterpret_cast<FreePageRun*>(base_ + i * kPageSize);
1228        if (free_page_runs_.find(fpr) != free_page_runs_.end()) {
1229          // Encountered a fresh free page run.
1230          DCHECK_EQ(remaining_curr_fpr_size, static_cast<size_t>(0));
1231          DCHECK(fpr->IsFree());
1232          DCHECK(curr_fpr == nullptr);
1233          DCHECK_EQ(curr_fpr_size, static_cast<size_t>(0));
1234          curr_fpr = fpr;
1235          curr_fpr_size = fpr->ByteSize(this);
1236          DCHECK_EQ(curr_fpr_size % kPageSize, static_cast<size_t>(0));
1237          remaining_curr_fpr_size = curr_fpr_size - kPageSize;
1238          stream << "[" << i << "]=" << (pm == kPageMapReleased ? "Released" : "Empty")
1239                 << " (FPR start) fpr_size=" << curr_fpr_size
1240                 << " remaining_fpr_size=" << remaining_curr_fpr_size << std::endl;
1241          if (remaining_curr_fpr_size == 0) {
1242            // Reset at the end of the current free page run.
1243            curr_fpr = nullptr;
1244            curr_fpr_size = 0;
1245          }
1246          stream << "curr_fpr=0x" << std::hex << reinterpret_cast<intptr_t>(curr_fpr) << std::endl;
1247          DCHECK_EQ(num_running_empty_pages, static_cast<size_t>(0));
1248        } else {
1249          // Still part of the current free page run.
1250          DCHECK_NE(num_running_empty_pages, static_cast<size_t>(0));
1251          DCHECK(curr_fpr != nullptr && curr_fpr_size > 0 && remaining_curr_fpr_size > 0);
1252          DCHECK_EQ(remaining_curr_fpr_size % kPageSize, static_cast<size_t>(0));
1253          DCHECK_GE(remaining_curr_fpr_size, static_cast<size_t>(kPageSize));
1254          remaining_curr_fpr_size -= kPageSize;
1255          stream << "[" << i << "]=Empty (FPR part)"
1256                 << " remaining_fpr_size=" << remaining_curr_fpr_size << std::endl;
1257          if (remaining_curr_fpr_size == 0) {
1258            // Reset at the end of the current free page run.
1259            curr_fpr = nullptr;
1260            curr_fpr_size = 0;
1261          }
1262        }
1263        num_running_empty_pages++;
1264        break;
1265      }
1266      case kPageMapLargeObject: {
1267        DCHECK_EQ(remaining_curr_fpr_size, static_cast<size_t>(0));
1268        num_running_empty_pages = 0;
1269        stream << "[" << i << "]=Large (start)" << std::endl;
1270        break;
1271      }
1272      case kPageMapLargeObjectPart:
1273        DCHECK_EQ(remaining_curr_fpr_size, static_cast<size_t>(0));
1274        num_running_empty_pages = 0;
1275        stream << "[" << i << "]=Large (part)" << std::endl;
1276        break;
1277      case kPageMapRun: {
1278        DCHECK_EQ(remaining_curr_fpr_size, static_cast<size_t>(0));
1279        num_running_empty_pages = 0;
1280        Run* run = reinterpret_cast<Run*>(base_ + i * kPageSize);
1281        size_t idx = run->size_bracket_idx_;
1282        stream << "[" << i << "]=Run (start)"
1283               << " idx=" << idx
1284               << " numOfPages=" << numOfPages[idx]
1285               << " is_thread_local=" << run->is_thread_local_
1286               << " is_all_free=" << (run->IsAllFree() ? 1 : 0)
1287               << std::endl;
1288        break;
1289      }
1290      case kPageMapRunPart:
1291        DCHECK_EQ(remaining_curr_fpr_size, static_cast<size_t>(0));
1292        num_running_empty_pages = 0;
1293        stream << "[" << i << "]=Run (part)" << std::endl;
1294        break;
1295      default:
1296        stream << "[" << i << "]=Unrecognizable page map type: " << pm;
1297        break;
1298    }
1299  }
1300  return stream.str();
1301}
1302
1303size_t RosAlloc::UsableSize(const void* ptr) {
1304  DCHECK_LE(base_, ptr);
1305  DCHECK_LT(ptr, base_ + footprint_);
1306  size_t pm_idx = RoundDownToPageMapIndex(ptr);
1307  MutexLock mu(Thread::Current(), lock_);
1308  switch (page_map_[pm_idx]) {
1309    case kPageMapReleased:
1310      // Fall-through.
1311    case kPageMapEmpty:
1312      LOG(FATAL) << "Unreachable - " << __PRETTY_FUNCTION__ << ": pm_idx=" << pm_idx << ", ptr="
1313                 << std::hex << reinterpret_cast<intptr_t>(ptr);
1314      break;
1315    case kPageMapLargeObject: {
1316      size_t num_pages = 1;
1317      size_t idx = pm_idx + 1;
1318      size_t end = page_map_size_;
1319      while (idx < end && page_map_[idx] == kPageMapLargeObjectPart) {
1320        num_pages++;
1321        idx++;
1322      }
1323      return num_pages * kPageSize;
1324    }
1325    case kPageMapLargeObjectPart:
1326      LOG(FATAL) << "Unreachable - " << __PRETTY_FUNCTION__ << ": pm_idx=" << pm_idx << ", ptr="
1327                 << std::hex << reinterpret_cast<intptr_t>(ptr);
1328      break;
1329    case kPageMapRun:
1330    case kPageMapRunPart: {
1331      // Find the beginning of the run.
1332      while (page_map_[pm_idx] != kPageMapRun) {
1333        pm_idx--;
1334        DCHECK_LT(pm_idx, capacity_ / kPageSize);
1335      }
1336      DCHECK_EQ(page_map_[pm_idx], kPageMapRun);
1337      Run* run = reinterpret_cast<Run*>(base_ + pm_idx * kPageSize);
1338      DCHECK_EQ(run->magic_num_, kMagicNum);
1339      size_t idx = run->size_bracket_idx_;
1340      size_t offset_from_slot_base = reinterpret_cast<const uint8_t*>(ptr)
1341          - (reinterpret_cast<uint8_t*>(run) + headerSizes[idx]);
1342      DCHECK_EQ(offset_from_slot_base % bracketSizes[idx], static_cast<size_t>(0));
1343      return IndexToBracketSize(idx);
1344    }
1345    default: {
1346      LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(page_map_[pm_idx]);
1347      break;
1348    }
1349  }
1350  return 0;
1351}
1352
1353bool RosAlloc::Trim() {
1354  MutexLock mu(Thread::Current(), lock_);
1355  FreePageRun* last_free_page_run;
1356  DCHECK_EQ(footprint_ % kPageSize, static_cast<size_t>(0));
1357  auto it = free_page_runs_.rbegin();
1358  if (it != free_page_runs_.rend() && (last_free_page_run = *it)->End(this) == base_ + footprint_) {
1359    // Remove the last free page run, if any.
1360    DCHECK(last_free_page_run->IsFree());
1361    DCHECK(IsFreePage(ToPageMapIndex(last_free_page_run)));
1362    DCHECK_EQ(last_free_page_run->ByteSize(this) % kPageSize, static_cast<size_t>(0));
1363    DCHECK_EQ(last_free_page_run->End(this), base_ + footprint_);
1364    free_page_runs_.erase(last_free_page_run);
1365    size_t decrement = last_free_page_run->ByteSize(this);
1366    size_t new_footprint = footprint_ - decrement;
1367    DCHECK_EQ(new_footprint % kPageSize, static_cast<size_t>(0));
1368    size_t new_num_of_pages = new_footprint / kPageSize;
1369    DCHECK_GE(page_map_size_, new_num_of_pages);
1370    // Zero out the tail of the page map.
1371    uint8_t* zero_begin = const_cast<uint8_t*>(page_map_) + new_num_of_pages;
1372    uint8_t* madvise_begin = AlignUp(zero_begin, kPageSize);
1373    DCHECK_LE(madvise_begin, page_map_mem_map_->End());
1374    size_t madvise_size = page_map_mem_map_->End() - madvise_begin;
1375    if (madvise_size > 0) {
1376      DCHECK_ALIGNED(madvise_begin, kPageSize);
1377      DCHECK_EQ(RoundUp(madvise_size, kPageSize), madvise_size);
1378      if (!kMadviseZeroes) {
1379        memset(madvise_begin, 0, madvise_size);
1380      }
1381      CHECK_EQ(madvise(madvise_begin, madvise_size, MADV_DONTNEED), 0);
1382    }
1383    if (madvise_begin - zero_begin) {
1384      memset(zero_begin, 0, madvise_begin - zero_begin);
1385    }
1386    page_map_size_ = new_num_of_pages;
1387    free_page_run_size_map_.resize(new_num_of_pages);
1388    DCHECK_EQ(free_page_run_size_map_.size(), new_num_of_pages);
1389    ArtRosAllocMoreCore(this, -(static_cast<intptr_t>(decrement)));
1390    if (kTraceRosAlloc) {
1391      LOG(INFO) << "RosAlloc::Trim() : decreased the footprint from "
1392                << footprint_ << " to " << new_footprint;
1393    }
1394    DCHECK_LT(new_footprint, footprint_);
1395    DCHECK_LT(new_footprint, capacity_);
1396    footprint_ = new_footprint;
1397    return true;
1398  }
1399  return false;
1400}
1401
1402void RosAlloc::InspectAll(void (*handler)(void* start, void* end, size_t used_bytes, void* callback_arg),
1403                          void* arg) {
1404  // Note: no need to use this to release pages as we already do so in FreePages().
1405  if (handler == nullptr) {
1406    return;
1407  }
1408  MutexLock mu(Thread::Current(), lock_);
1409  size_t pm_end = page_map_size_;
1410  size_t i = 0;
1411  while (i < pm_end) {
1412    uint8_t pm = page_map_[i];
1413    switch (pm) {
1414      case kPageMapReleased:
1415        // Fall-through.
1416      case kPageMapEmpty: {
1417        // The start of a free page run.
1418        FreePageRun* fpr = reinterpret_cast<FreePageRun*>(base_ + i * kPageSize);
1419        DCHECK(free_page_runs_.find(fpr) != free_page_runs_.end());
1420        size_t fpr_size = fpr->ByteSize(this);
1421        DCHECK_ALIGNED(fpr_size, kPageSize);
1422        void* start = fpr;
1423        if (kIsDebugBuild) {
1424          // In the debug build, the first page of a free page run
1425          // contains a magic number for debugging. Exclude it.
1426          start = reinterpret_cast<uint8_t*>(fpr) + kPageSize;
1427        }
1428        void* end = reinterpret_cast<uint8_t*>(fpr) + fpr_size;
1429        handler(start, end, 0, arg);
1430        size_t num_pages = fpr_size / kPageSize;
1431        if (kIsDebugBuild) {
1432          for (size_t j = i + 1; j < i + num_pages; ++j) {
1433            DCHECK(IsFreePage(j));
1434          }
1435        }
1436        i += fpr_size / kPageSize;
1437        DCHECK_LE(i, pm_end);
1438        break;
1439      }
1440      case kPageMapLargeObject: {
1441        // The start of a large object.
1442        size_t num_pages = 1;
1443        size_t idx = i + 1;
1444        while (idx < pm_end && page_map_[idx] == kPageMapLargeObjectPart) {
1445          num_pages++;
1446          idx++;
1447        }
1448        void* start = base_ + i * kPageSize;
1449        void* end = base_ + (i + num_pages) * kPageSize;
1450        size_t used_bytes = num_pages * kPageSize;
1451        handler(start, end, used_bytes, arg);
1452        if (kIsDebugBuild) {
1453          for (size_t j = i + 1; j < i + num_pages; ++j) {
1454            DCHECK_EQ(page_map_[j], kPageMapLargeObjectPart);
1455          }
1456        }
1457        i += num_pages;
1458        DCHECK_LE(i, pm_end);
1459        break;
1460      }
1461      case kPageMapLargeObjectPart:
1462        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(pm);
1463        break;
1464      case kPageMapRun: {
1465        // The start of a run.
1466        Run* run = reinterpret_cast<Run*>(base_ + i * kPageSize);
1467        DCHECK_EQ(run->magic_num_, kMagicNum);
1468        // The dedicated full run doesn't contain any real allocations, don't visit the slots in
1469        // there.
1470        run->InspectAllSlots(handler, arg);
1471        size_t num_pages = numOfPages[run->size_bracket_idx_];
1472        if (kIsDebugBuild) {
1473          for (size_t j = i + 1; j < i + num_pages; ++j) {
1474            DCHECK_EQ(page_map_[j], kPageMapRunPart);
1475          }
1476        }
1477        i += num_pages;
1478        DCHECK_LE(i, pm_end);
1479        break;
1480      }
1481      case kPageMapRunPart:
1482        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(pm);
1483        break;
1484      default:
1485        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(pm);
1486        break;
1487    }
1488  }
1489}
1490
1491size_t RosAlloc::Footprint() {
1492  MutexLock mu(Thread::Current(), lock_);
1493  return footprint_;
1494}
1495
1496size_t RosAlloc::FootprintLimit() {
1497  MutexLock mu(Thread::Current(), lock_);
1498  return capacity_;
1499}
1500
1501void RosAlloc::SetFootprintLimit(size_t new_capacity) {
1502  MutexLock mu(Thread::Current(), lock_);
1503  DCHECK_EQ(RoundUp(new_capacity, kPageSize), new_capacity);
1504  // Only growing is supported here. But Trim() is supported.
1505  if (capacity_ < new_capacity) {
1506    CHECK_LE(new_capacity, max_capacity_);
1507    capacity_ = new_capacity;
1508    VLOG(heap) << "new capacity=" << capacity_;
1509  }
1510}
1511
1512// Below may be called by mutator itself just before thread termination.
1513size_t RosAlloc::RevokeThreadLocalRuns(Thread* thread) {
1514  Thread* self = Thread::Current();
1515  size_t free_bytes = 0U;
1516  for (size_t idx = 0; idx < kNumThreadLocalSizeBrackets; idx++) {
1517    MutexLock mu(self, *size_bracket_locks_[idx]);
1518    Run* thread_local_run = reinterpret_cast<Run*>(thread->GetRosAllocRun(idx));
1519    CHECK(thread_local_run != nullptr);
1520    // Invalid means already revoked.
1521    DCHECK(thread_local_run->IsThreadLocal());
1522    if (thread_local_run != dedicated_full_run_) {
1523      // Note the thread local run may not be full here.
1524      thread->SetRosAllocRun(idx, dedicated_full_run_);
1525      DCHECK_EQ(thread_local_run->magic_num_, kMagicNum);
1526      // Count the number of free slots left.
1527      size_t num_free_slots = thread_local_run->NumberOfFreeSlots();
1528      free_bytes += num_free_slots * bracketSizes[idx];
1529      // The above bracket index lock guards thread local free list to avoid race condition
1530      // with unioning bulk free list to thread local free list by GC thread in BulkFree.
1531      // If thread local run is true, GC thread will help update thread local free list
1532      // in BulkFree. And the latest thread local free list will be merged to free list
1533      // either when this thread local run is full or when revoking this run here. In this
1534      // case the free list wll be updated. If thread local run is false, GC thread will help
1535      // merge bulk free list in next BulkFree.
1536      // Thus no need to merge bulk free list to free list again here.
1537      bool dont_care;
1538      thread_local_run->MergeThreadLocalFreeListToFreeList(&dont_care);
1539      thread_local_run->SetIsThreadLocal(false);
1540      DCHECK(non_full_runs_[idx].find(thread_local_run) == non_full_runs_[idx].end());
1541      DCHECK(full_runs_[idx].find(thread_local_run) == full_runs_[idx].end());
1542      RevokeRun(self, idx, thread_local_run);
1543    }
1544  }
1545  return free_bytes;
1546}
1547
1548void RosAlloc::RevokeRun(Thread* self, size_t idx, Run* run) {
1549  size_bracket_locks_[idx]->AssertHeld(self);
1550  DCHECK(run != dedicated_full_run_);
1551  if (run->IsFull()) {
1552    if (kIsDebugBuild) {
1553      full_runs_[idx].insert(run);
1554      DCHECK(full_runs_[idx].find(run) != full_runs_[idx].end());
1555      if (kTraceRosAlloc) {
1556        LOG(INFO) << __PRETTY_FUNCTION__  << " : Inserted run 0x" << std::hex
1557                  << reinterpret_cast<intptr_t>(run)
1558                  << " into full_runs_[" << std::dec << idx << "]";
1559      }
1560    }
1561  } else if (run->IsAllFree()) {
1562    run->ZeroHeaderAndSlotHeaders();
1563    MutexLock mu(self, lock_);
1564    FreePages(self, run, true);
1565  } else {
1566    non_full_runs_[idx].insert(run);
1567    DCHECK(non_full_runs_[idx].find(run) != non_full_runs_[idx].end());
1568    if (kTraceRosAlloc) {
1569      LOG(INFO) << __PRETTY_FUNCTION__ << " : Inserted run 0x" << std::hex
1570                << reinterpret_cast<intptr_t>(run)
1571                << " into non_full_runs_[" << std::dec << idx << "]";
1572    }
1573  }
1574}
1575
1576void RosAlloc::RevokeThreadUnsafeCurrentRuns() {
1577  // Revoke the current runs which share the same idx as thread local runs.
1578  Thread* self = Thread::Current();
1579  for (size_t idx = 0; idx < kNumThreadLocalSizeBrackets; ++idx) {
1580    MutexLock mu(self, *size_bracket_locks_[idx]);
1581    if (current_runs_[idx] != dedicated_full_run_) {
1582      RevokeRun(self, idx, current_runs_[idx]);
1583      current_runs_[idx] = dedicated_full_run_;
1584    }
1585  }
1586}
1587
1588size_t RosAlloc::RevokeAllThreadLocalRuns() {
1589  // This is called when a mutator thread won't allocate such as at
1590  // the Zygote creation time or during the GC pause.
1591  MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
1592  MutexLock mu2(Thread::Current(), *Locks::thread_list_lock_);
1593  std::list<Thread*> thread_list = Runtime::Current()->GetThreadList()->GetList();
1594  size_t free_bytes = 0U;
1595  for (Thread* thread : thread_list) {
1596    free_bytes += RevokeThreadLocalRuns(thread);
1597  }
1598  RevokeThreadUnsafeCurrentRuns();
1599  return free_bytes;
1600}
1601
1602void RosAlloc::AssertThreadLocalRunsAreRevoked(Thread* thread) {
1603  if (kIsDebugBuild) {
1604    Thread* self = Thread::Current();
1605    // Avoid race conditions on the bulk free bit maps with BulkFree() (GC).
1606    ReaderMutexLock wmu(self, bulk_free_lock_);
1607    for (size_t idx = 0; idx < kNumThreadLocalSizeBrackets; idx++) {
1608      MutexLock mu(self, *size_bracket_locks_[idx]);
1609      Run* thread_local_run = reinterpret_cast<Run*>(thread->GetRosAllocRun(idx));
1610      DCHECK(thread_local_run == nullptr || thread_local_run == dedicated_full_run_);
1611    }
1612  }
1613}
1614
1615void RosAlloc::AssertAllThreadLocalRunsAreRevoked() {
1616  if (kIsDebugBuild) {
1617    Thread* self = Thread::Current();
1618    MutexLock shutdown_mu(self, *Locks::runtime_shutdown_lock_);
1619    MutexLock thread_list_mu(self, *Locks::thread_list_lock_);
1620    std::list<Thread*> thread_list = Runtime::Current()->GetThreadList()->GetList();
1621    for (Thread* t : thread_list) {
1622      AssertThreadLocalRunsAreRevoked(t);
1623    }
1624    for (size_t idx = 0; idx < kNumThreadLocalSizeBrackets; ++idx) {
1625      MutexLock brackets_mu(self, *size_bracket_locks_[idx]);
1626      CHECK_EQ(current_runs_[idx], dedicated_full_run_);
1627    }
1628  }
1629}
1630
1631void RosAlloc::Initialize() {
1632  // bracketSizes.
1633  static_assert(kNumRegularSizeBrackets == kNumOfSizeBrackets - 2,
1634                "There should be two non-regular brackets");
1635  for (size_t i = 0; i < kNumOfSizeBrackets; i++) {
1636    if (i < kNumThreadLocalSizeBrackets) {
1637      bracketSizes[i] = kThreadLocalBracketQuantumSize * (i + 1);
1638    } else if (i < kNumRegularSizeBrackets) {
1639      bracketSizes[i] = kBracketQuantumSize * (i - kNumThreadLocalSizeBrackets + 1) +
1640          (kThreadLocalBracketQuantumSize *  kNumThreadLocalSizeBrackets);
1641    } else if (i == kNumOfSizeBrackets - 2) {
1642      bracketSizes[i] = 1 * KB;
1643    } else {
1644      DCHECK_EQ(i, kNumOfSizeBrackets - 1);
1645      bracketSizes[i] = 2 * KB;
1646    }
1647    if (kTraceRosAlloc) {
1648      LOG(INFO) << "bracketSizes[" << i << "]=" << bracketSizes[i];
1649    }
1650  }
1651  // numOfPages.
1652  for (size_t i = 0; i < kNumOfSizeBrackets; i++) {
1653    if (i < kNumThreadLocalSizeBrackets) {
1654      numOfPages[i] = 1;
1655    } else if (i < (kNumThreadLocalSizeBrackets + kNumRegularSizeBrackets) / 2) {
1656      numOfPages[i] = 1;
1657    } else if (i < kNumRegularSizeBrackets) {
1658      numOfPages[i] = 1;
1659    } else if (i == kNumOfSizeBrackets - 2) {
1660      numOfPages[i] = 2;
1661    } else {
1662      DCHECK_EQ(i, kNumOfSizeBrackets - 1);
1663      numOfPages[i] = 4;
1664    }
1665    if (kTraceRosAlloc) {
1666      LOG(INFO) << "numOfPages[" << i << "]=" << numOfPages[i];
1667    }
1668  }
1669  // Compute numOfSlots and slotOffsets.
1670  for (size_t i = 0; i < kNumOfSizeBrackets; i++) {
1671    size_t bracket_size = bracketSizes[i];
1672    size_t run_size = kPageSize * numOfPages[i];
1673    size_t max_num_of_slots = run_size / bracket_size;
1674    // Compute the actual number of slots by taking the header and
1675    // alignment into account.
1676    size_t fixed_header_size = RoundUp(Run::fixed_header_size(), sizeof(uint64_t));
1677    DCHECK_EQ(fixed_header_size, 80U);
1678    size_t header_size = 0;
1679    size_t num_of_slots = 0;
1680    // Search for the maximum number of slots that allows enough space
1681    // for the header.
1682    for (int s = max_num_of_slots; s >= 0; s--) {
1683      size_t tmp_slots_size = bracket_size * s;
1684      size_t tmp_unaligned_header_size = fixed_header_size;
1685      // Align up the unaligned header size. bracket_size may not be a power of two.
1686      size_t tmp_header_size = (tmp_unaligned_header_size % bracket_size == 0) ?
1687          tmp_unaligned_header_size :
1688          tmp_unaligned_header_size + (bracket_size - tmp_unaligned_header_size % bracket_size);
1689      DCHECK_EQ(tmp_header_size % bracket_size, 0U);
1690      DCHECK_EQ(tmp_header_size % sizeof(uint64_t), 0U);
1691      if (tmp_slots_size + tmp_header_size <= run_size) {
1692        // Found the right number of slots, that is, there was enough
1693        // space for the header (including the bit maps.)
1694        num_of_slots = s;
1695        header_size = tmp_header_size;
1696        break;
1697      }
1698    }
1699    DCHECK_GT(num_of_slots, 0U) << i;
1700    DCHECK_GT(header_size, 0U) << i;
1701    // Add the padding for the alignment remainder.
1702    header_size += run_size % bracket_size;
1703    DCHECK_EQ(header_size + num_of_slots * bracket_size, run_size);
1704    numOfSlots[i] = num_of_slots;
1705    headerSizes[i] = header_size;
1706    if (kTraceRosAlloc) {
1707      LOG(INFO) << "numOfSlots[" << i << "]=" << numOfSlots[i]
1708                << ", headerSizes[" << i << "]=" << headerSizes[i];
1709    }
1710  }
1711  // Set up the dedicated full run so that nobody can successfully allocate from it.
1712  if (kIsDebugBuild) {
1713    dedicated_full_run_->magic_num_ = kMagicNum;
1714  }
1715  // It doesn't matter which size bracket we use since the main goal is to have the allocation
1716  // fail 100% of the time you attempt to allocate into the dedicated full run.
1717  dedicated_full_run_->size_bracket_idx_ = 0;
1718  DCHECK_EQ(dedicated_full_run_->FreeList()->Size(), 0U);  // It looks full.
1719  dedicated_full_run_->SetIsThreadLocal(true);
1720
1721  // The smallest bracket size must be at least as large as the sizeof(Slot).
1722  DCHECK_LE(sizeof(Slot), bracketSizes[0]) << "sizeof(Slot) <= the smallest bracket size";
1723  // Check the invariants between the max bracket sizes and the number of brackets.
1724  DCHECK_EQ(kMaxThreadLocalBracketSize, bracketSizes[kNumThreadLocalSizeBrackets - 1]);
1725  DCHECK_EQ(kMaxRegularBracketSize, bracketSizes[kNumRegularSizeBrackets - 1]);
1726}
1727
1728void RosAlloc::BytesAllocatedCallback(void* start ATTRIBUTE_UNUSED, void* end ATTRIBUTE_UNUSED,
1729                                      size_t used_bytes, void* arg) {
1730  if (used_bytes == 0) {
1731    return;
1732  }
1733  size_t* bytes_allocated = reinterpret_cast<size_t*>(arg);
1734  *bytes_allocated += used_bytes;
1735}
1736
1737void RosAlloc::ObjectsAllocatedCallback(void* start ATTRIBUTE_UNUSED, void* end ATTRIBUTE_UNUSED,
1738                                        size_t used_bytes, void* arg) {
1739  if (used_bytes == 0) {
1740    return;
1741  }
1742  size_t* objects_allocated = reinterpret_cast<size_t*>(arg);
1743  ++(*objects_allocated);
1744}
1745
1746void RosAlloc::Verify() {
1747  Thread* self = Thread::Current();
1748  CHECK(Locks::mutator_lock_->IsExclusiveHeld(self))
1749      << "The mutator locks isn't exclusively locked at " << __PRETTY_FUNCTION__;
1750  MutexLock thread_list_mu(self, *Locks::thread_list_lock_);
1751  ReaderMutexLock wmu(self, bulk_free_lock_);
1752  std::vector<Run*> runs;
1753  {
1754    MutexLock lock_mu(self, lock_);
1755    size_t pm_end = page_map_size_;
1756    size_t i = 0;
1757    size_t memory_tool_modifier =  is_running_on_memory_tool_ ?
1758        2 * ::art::gc::space::kDefaultMemoryToolRedZoneBytes :  // Redzones before and after.
1759        0;
1760    while (i < pm_end) {
1761      uint8_t pm = page_map_[i];
1762      switch (pm) {
1763        case kPageMapReleased:
1764          // Fall-through.
1765        case kPageMapEmpty: {
1766          // The start of a free page run.
1767          FreePageRun* fpr = reinterpret_cast<FreePageRun*>(base_ + i * kPageSize);
1768          DCHECK_EQ(fpr->magic_num_, kMagicNumFree);
1769          CHECK(free_page_runs_.find(fpr) != free_page_runs_.end())
1770              << "An empty page must belong to the free page run set";
1771          size_t fpr_size = fpr->ByteSize(this);
1772          CHECK_ALIGNED(fpr_size, kPageSize)
1773              << "A free page run size isn't page-aligned : " << fpr_size;
1774          size_t num_pages = fpr_size / kPageSize;
1775          CHECK_GT(num_pages, static_cast<uintptr_t>(0))
1776              << "A free page run size must be > 0 : " << fpr_size;
1777          for (size_t j = i + 1; j < i + num_pages; ++j) {
1778            CHECK(IsFreePage(j))
1779                << "A mismatch between the page map table for kPageMapEmpty "
1780                << " at page index " << j
1781                << " and the free page run size : page index range : "
1782                << i << " to " << (i + num_pages) << std::endl << DumpPageMap();
1783          }
1784          i += num_pages;
1785          CHECK_LE(i, pm_end) << "Page map index " << i << " out of range < " << pm_end
1786                              << std::endl << DumpPageMap();
1787          break;
1788        }
1789        case kPageMapLargeObject: {
1790          // The start of a large object.
1791          size_t num_pages = 1;
1792          size_t idx = i + 1;
1793          while (idx < pm_end && page_map_[idx] == kPageMapLargeObjectPart) {
1794            num_pages++;
1795            idx++;
1796          }
1797          uint8_t* start = base_ + i * kPageSize;
1798          if (is_running_on_memory_tool_) {
1799            start += ::art::gc::space::kDefaultMemoryToolRedZoneBytes;
1800          }
1801          mirror::Object* obj = reinterpret_cast<mirror::Object*>(start);
1802          size_t obj_size = obj->SizeOf();
1803          CHECK_GT(obj_size + memory_tool_modifier, kLargeSizeThreshold)
1804              << "A rosalloc large object size must be > " << kLargeSizeThreshold;
1805          CHECK_EQ(num_pages, RoundUp(obj_size + memory_tool_modifier, kPageSize) / kPageSize)
1806              << "A rosalloc large object size " << obj_size + memory_tool_modifier
1807              << " does not match the page map table " << (num_pages * kPageSize)
1808              << std::endl << DumpPageMap();
1809          i += num_pages;
1810          CHECK_LE(i, pm_end) << "Page map index " << i << " out of range < " << pm_end
1811                              << std::endl << DumpPageMap();
1812          break;
1813        }
1814        case kPageMapLargeObjectPart:
1815          LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(pm) << std::endl << DumpPageMap();
1816          break;
1817        case kPageMapRun: {
1818          // The start of a run.
1819          Run* run = reinterpret_cast<Run*>(base_ + i * kPageSize);
1820          DCHECK_EQ(run->magic_num_, kMagicNum);
1821          size_t idx = run->size_bracket_idx_;
1822          CHECK_LT(idx, kNumOfSizeBrackets) << "Out of range size bracket index : " << idx;
1823          size_t num_pages = numOfPages[idx];
1824          CHECK_GT(num_pages, static_cast<uintptr_t>(0))
1825              << "Run size must be > 0 : " << num_pages;
1826          for (size_t j = i + 1; j < i + num_pages; ++j) {
1827            CHECK_EQ(page_map_[j], kPageMapRunPart)
1828                << "A mismatch between the page map table for kPageMapRunPart "
1829                << " at page index " << j
1830                << " and the run size : page index range " << i << " to " << (i + num_pages)
1831                << std::endl << DumpPageMap();
1832          }
1833          // Don't verify the dedicated_full_run_ since it doesn't have any real allocations.
1834          runs.push_back(run);
1835          i += num_pages;
1836          CHECK_LE(i, pm_end) << "Page map index " << i << " out of range < " << pm_end
1837                              << std::endl << DumpPageMap();
1838          break;
1839        }
1840        case kPageMapRunPart:
1841          // Fall-through.
1842        default:
1843          LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(pm) << std::endl << DumpPageMap();
1844          break;
1845      }
1846    }
1847  }
1848  std::list<Thread*> threads = Runtime::Current()->GetThreadList()->GetList();
1849  for (Thread* thread : threads) {
1850    for (size_t i = 0; i < kNumThreadLocalSizeBrackets; ++i) {
1851      MutexLock brackets_mu(self, *size_bracket_locks_[i]);
1852      Run* thread_local_run = reinterpret_cast<Run*>(thread->GetRosAllocRun(i));
1853      CHECK(thread_local_run != nullptr);
1854      CHECK(thread_local_run->IsThreadLocal());
1855      CHECK(thread_local_run == dedicated_full_run_ ||
1856            thread_local_run->size_bracket_idx_ == i);
1857    }
1858  }
1859  for (size_t i = 0; i < kNumOfSizeBrackets; i++) {
1860    MutexLock brackets_mu(self, *size_bracket_locks_[i]);
1861    Run* current_run = current_runs_[i];
1862    CHECK(current_run != nullptr);
1863    if (current_run != dedicated_full_run_) {
1864      // The dedicated full run is currently marked as thread local.
1865      CHECK(!current_run->IsThreadLocal());
1866      CHECK_EQ(current_run->size_bracket_idx_, i);
1867    }
1868  }
1869  // Call Verify() here for the lock order.
1870  for (auto& run : runs) {
1871    run->Verify(self, this, is_running_on_memory_tool_);
1872  }
1873}
1874
1875void RosAlloc::Run::Verify(Thread* self, RosAlloc* rosalloc, bool running_on_memory_tool) {
1876  DCHECK_EQ(magic_num_, kMagicNum) << "Bad magic number : " << Dump();
1877  const size_t idx = size_bracket_idx_;
1878  CHECK_LT(idx, kNumOfSizeBrackets) << "Out of range size bracket index : " << Dump();
1879  uint8_t* slot_base = reinterpret_cast<uint8_t*>(this) + headerSizes[idx];
1880  const size_t num_slots = numOfSlots[idx];
1881  size_t bracket_size = IndexToBracketSize(idx);
1882  CHECK_EQ(slot_base + num_slots * bracket_size,
1883           reinterpret_cast<uint8_t*>(this) + numOfPages[idx] * kPageSize)
1884      << "Mismatch in the end address of the run " << Dump();
1885  // Check that the bulk free list is empty. It's only used during BulkFree().
1886  CHECK(IsBulkFreeListEmpty()) << "The bulk free isn't empty " << Dump();
1887  // Check the thread local runs, the current runs, and the run sets.
1888  if (IsThreadLocal()) {
1889    // If it's a thread local run, then it must be pointed to by an owner thread.
1890    bool owner_found = false;
1891    std::list<Thread*> thread_list = Runtime::Current()->GetThreadList()->GetList();
1892    for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
1893      Thread* thread = *it;
1894      for (size_t i = 0; i < kNumThreadLocalSizeBrackets; i++) {
1895        MutexLock mu(self, *rosalloc->size_bracket_locks_[i]);
1896        Run* thread_local_run = reinterpret_cast<Run*>(thread->GetRosAllocRun(i));
1897        if (thread_local_run == this) {
1898          CHECK(!owner_found)
1899              << "A thread local run has more than one owner thread " << Dump();
1900          CHECK_EQ(i, idx)
1901              << "A mismatching size bracket index in a thread local run " << Dump();
1902          owner_found = true;
1903        }
1904      }
1905    }
1906    CHECK(owner_found) << "A thread local run has no owner thread " << Dump();
1907  } else {
1908    // If it's not thread local, check that the thread local free list is empty.
1909    CHECK(IsThreadLocalFreeListEmpty())
1910        << "A non-thread-local run's thread local free list isn't empty "
1911        << Dump();
1912    // Check if it's a current run for the size bracket.
1913    bool is_current_run = false;
1914    for (size_t i = 0; i < kNumOfSizeBrackets; i++) {
1915      MutexLock mu(self, *rosalloc->size_bracket_locks_[i]);
1916      Run* current_run = rosalloc->current_runs_[i];
1917      if (idx == i) {
1918        if (this == current_run) {
1919          is_current_run = true;
1920        }
1921      } else {
1922        // If the size bucket index does not match, then it must not
1923        // be a current run.
1924        CHECK_NE(this, current_run)
1925            << "A current run points to a run with a wrong size bracket index " << Dump();
1926      }
1927    }
1928    // If it's neither a thread local or current run, then it must be
1929    // in a run set.
1930    if (!is_current_run) {
1931      MutexLock mu(self, rosalloc->lock_);
1932      auto& non_full_runs = rosalloc->non_full_runs_[idx];
1933      // If it's all free, it must be a free page run rather than a run.
1934      CHECK(!IsAllFree()) << "A free run must be in a free page run set " << Dump();
1935      if (!IsFull()) {
1936        // If it's not full, it must in the non-full run set.
1937        CHECK(non_full_runs.find(this) != non_full_runs.end())
1938            << "A non-full run isn't in the non-full run set " << Dump();
1939      } else {
1940        // If it's full, it must in the full run set (debug build only.)
1941        if (kIsDebugBuild) {
1942          auto& full_runs = rosalloc->full_runs_[idx];
1943          CHECK(full_runs.find(this) != full_runs.end())
1944              << " A full run isn't in the full run set " << Dump();
1945        }
1946      }
1947    }
1948  }
1949  // Check each slot.
1950  size_t memory_tool_modifier = running_on_memory_tool ?
1951      2 * ::art::gc::space::kDefaultMemoryToolRedZoneBytes :
1952      0U;
1953  // TODO: reuse InspectAllSlots().
1954  std::unique_ptr<bool[]> is_free(new bool[num_slots]());  // zero initialized
1955  // Mark the free slots and the remaining ones are allocated.
1956  for (Slot* slot = free_list_.Head(); slot != nullptr; slot = slot->Next()) {
1957    size_t slot_idx = SlotIndex(slot);
1958    DCHECK_LT(slot_idx, num_slots);
1959    is_free[slot_idx] = true;
1960  }
1961  if (IsThreadLocal()) {
1962    for (Slot* slot = thread_local_free_list_.Head(); slot != nullptr; slot = slot->Next()) {
1963      size_t slot_idx = SlotIndex(slot);
1964      DCHECK_LT(slot_idx, num_slots);
1965      is_free[slot_idx] = true;
1966    }
1967  }
1968  for (size_t slot_idx = 0; slot_idx < num_slots; ++slot_idx) {
1969    uint8_t* slot_addr = slot_base + slot_idx * bracket_size;
1970    if (running_on_memory_tool) {
1971      slot_addr += ::art::gc::space::kDefaultMemoryToolRedZoneBytes;
1972    }
1973    if (!is_free[slot_idx]) {
1974      // The slot is allocated
1975      mirror::Object* obj = reinterpret_cast<mirror::Object*>(slot_addr);
1976      size_t obj_size = obj->SizeOf();
1977      CHECK_LE(obj_size + memory_tool_modifier, kLargeSizeThreshold)
1978          << "A run slot contains a large object " << Dump();
1979      CHECK_EQ(SizeToIndex(obj_size + memory_tool_modifier), idx)
1980          << PrettyTypeOf(obj) << " "
1981          << "obj_size=" << obj_size << "(" << obj_size + memory_tool_modifier << "), idx=" << idx
1982          << " A run slot contains an object with wrong size " << Dump();
1983    }
1984  }
1985}
1986
1987size_t RosAlloc::ReleasePages() {
1988  VLOG(heap) << "RosAlloc::ReleasePages()";
1989  DCHECK(!DoesReleaseAllPages());
1990  Thread* self = Thread::Current();
1991  size_t reclaimed_bytes = 0;
1992  size_t i = 0;
1993  // Check the page map size which might have changed due to grow/shrink.
1994  while (i < page_map_size_) {
1995    // Reading the page map without a lock is racy but the race is benign since it should only
1996    // result in occasionally not releasing pages which we could release.
1997    uint8_t pm = page_map_[i];
1998    switch (pm) {
1999      case kPageMapReleased:
2000        // Fall through.
2001      case kPageMapEmpty: {
2002        // This is currently the start of a free page run.
2003        // Acquire the lock to prevent other threads racing in and modifying the page map.
2004        MutexLock mu(self, lock_);
2005        // Check that it's still empty after we acquired the lock since another thread could have
2006        // raced in and placed an allocation here.
2007        if (IsFreePage(i)) {
2008          // Free page runs can start with a released page if we coalesced a released page free
2009          // page run with an empty page run.
2010          FreePageRun* fpr = reinterpret_cast<FreePageRun*>(base_ + i * kPageSize);
2011          // There is a race condition where FreePage can coalesce fpr with the previous
2012          // free page run before we acquire lock_. In that case free_page_runs_.find will not find
2013          // a run starting at fpr. To handle this race, we skip reclaiming the page range and go
2014          // to the next page.
2015          if (free_page_runs_.find(fpr) != free_page_runs_.end()) {
2016            size_t fpr_size = fpr->ByteSize(this);
2017            DCHECK_ALIGNED(fpr_size, kPageSize);
2018            uint8_t* start = reinterpret_cast<uint8_t*>(fpr);
2019            reclaimed_bytes += ReleasePageRange(start, start + fpr_size);
2020            size_t pages = fpr_size / kPageSize;
2021            CHECK_GT(pages, 0U) << "Infinite loop probable";
2022            i += pages;
2023            DCHECK_LE(i, page_map_size_);
2024            break;
2025          }
2026        }
2027        FALLTHROUGH_INTENDED;
2028      }
2029      case kPageMapLargeObject:      // Fall through.
2030      case kPageMapLargeObjectPart:  // Fall through.
2031      case kPageMapRun:              // Fall through.
2032      case kPageMapRunPart:          // Fall through.
2033        ++i;
2034        break;  // Skip.
2035      default:
2036        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(pm);
2037        break;
2038    }
2039  }
2040  return reclaimed_bytes;
2041}
2042
2043size_t RosAlloc::ReleasePageRange(uint8_t* start, uint8_t* end) {
2044  DCHECK_ALIGNED(start, kPageSize);
2045  DCHECK_ALIGNED(end, kPageSize);
2046  DCHECK_LT(start, end);
2047  if (kIsDebugBuild) {
2048    // In the debug build, the first page of a free page run
2049    // contains a magic number for debugging. Exclude it.
2050    start += kPageSize;
2051
2052    // Single pages won't be released.
2053    if (start == end) {
2054      return 0;
2055    }
2056  }
2057  if (!kMadviseZeroes) {
2058    // TODO: Do this when we resurrect the page instead.
2059    memset(start, 0, end - start);
2060  }
2061  CHECK_EQ(madvise(start, end - start, MADV_DONTNEED), 0);
2062  size_t pm_idx = ToPageMapIndex(start);
2063  size_t reclaimed_bytes = 0;
2064  // Calculate reclaimed bytes and upate page map.
2065  const size_t max_idx = pm_idx + (end - start) / kPageSize;
2066  for (; pm_idx < max_idx; ++pm_idx) {
2067    DCHECK(IsFreePage(pm_idx));
2068    if (page_map_[pm_idx] == kPageMapEmpty) {
2069      // Mark the page as released and update how many bytes we released.
2070      reclaimed_bytes += kPageSize;
2071      page_map_[pm_idx] = kPageMapReleased;
2072    }
2073  }
2074  return reclaimed_bytes;
2075}
2076
2077void RosAlloc::LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) {
2078  Thread* self = Thread::Current();
2079  size_t largest_continuous_free_pages = 0;
2080  WriterMutexLock wmu(self, bulk_free_lock_);
2081  MutexLock mu(self, lock_);
2082  for (FreePageRun* fpr : free_page_runs_) {
2083    largest_continuous_free_pages = std::max(largest_continuous_free_pages,
2084                                             fpr->ByteSize(this));
2085  }
2086  if (failed_alloc_bytes > kLargeSizeThreshold) {
2087    // Large allocation.
2088    size_t required_bytes = RoundUp(failed_alloc_bytes, kPageSize);
2089    if (required_bytes > largest_continuous_free_pages) {
2090      os << "; failed due to fragmentation (required continguous free "
2091         << required_bytes << " bytes where largest contiguous free "
2092         <<  largest_continuous_free_pages << " bytes)";
2093    }
2094  } else {
2095    // Non-large allocation.
2096    size_t required_bytes = numOfPages[SizeToIndex(failed_alloc_bytes)] * kPageSize;
2097    if (required_bytes > largest_continuous_free_pages) {
2098      os << "; failed due to fragmentation (required continguous free "
2099         << required_bytes << " bytes for a new buffer where largest contiguous free "
2100         <<  largest_continuous_free_pages << " bytes)";
2101    }
2102  }
2103}
2104
2105void RosAlloc::DumpStats(std::ostream& os) {
2106  Thread* self = Thread::Current();
2107  CHECK(Locks::mutator_lock_->IsExclusiveHeld(self))
2108      << "The mutator locks isn't exclusively locked at " << __PRETTY_FUNCTION__;
2109  size_t num_large_objects = 0;
2110  size_t num_pages_large_objects = 0;
2111  // These arrays are zero initialized.
2112  std::unique_ptr<size_t[]> num_runs(new size_t[kNumOfSizeBrackets]());
2113  std::unique_ptr<size_t[]> num_pages_runs(new size_t[kNumOfSizeBrackets]());
2114  std::unique_ptr<size_t[]> num_slots(new size_t[kNumOfSizeBrackets]());
2115  std::unique_ptr<size_t[]> num_used_slots(new size_t[kNumOfSizeBrackets]());
2116  std::unique_ptr<size_t[]> num_metadata_bytes(new size_t[kNumOfSizeBrackets]());
2117  ReaderMutexLock rmu(self, bulk_free_lock_);
2118  MutexLock lock_mu(self, lock_);
2119  for (size_t i = 0; i < page_map_size_; ) {
2120    uint8_t pm = page_map_[i];
2121    switch (pm) {
2122      case kPageMapReleased:
2123      case kPageMapEmpty:
2124        ++i;
2125        break;
2126      case kPageMapLargeObject: {
2127        size_t num_pages = 1;
2128        size_t idx = i + 1;
2129        while (idx < page_map_size_ && page_map_[idx] == kPageMapLargeObjectPart) {
2130          num_pages++;
2131          idx++;
2132        }
2133        num_large_objects++;
2134        num_pages_large_objects += num_pages;
2135        i += num_pages;
2136        break;
2137      }
2138      case kPageMapLargeObjectPart:
2139        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(pm) << std::endl
2140                   << DumpPageMap();
2141        break;
2142      case kPageMapRun: {
2143        Run* run = reinterpret_cast<Run*>(base_ + i * kPageSize);
2144        size_t idx = run->size_bracket_idx_;
2145        size_t num_pages = numOfPages[idx];
2146        num_runs[idx]++;
2147        num_pages_runs[idx] += num_pages;
2148        num_slots[idx] += numOfSlots[idx];
2149        size_t num_free_slots = run->NumberOfFreeSlots();
2150        num_used_slots[idx] += numOfSlots[idx] - num_free_slots;
2151        num_metadata_bytes[idx] += headerSizes[idx];
2152        i += num_pages;
2153        break;
2154      }
2155      case kPageMapRunPart:
2156        // Fall-through.
2157      default:
2158        LOG(FATAL) << "Unreachable - page map type: " << static_cast<int>(pm) << std::endl
2159                   << DumpPageMap();
2160        break;
2161    }
2162  }
2163  os << "RosAlloc stats:\n";
2164  for (size_t i = 0; i < kNumOfSizeBrackets; ++i) {
2165    os << "Bracket " << i << " (" << bracketSizes[i] << "):"
2166       << " #runs=" << num_runs[i]
2167       << " #pages=" << num_pages_runs[i]
2168       << " (" << PrettySize(num_pages_runs[i] * kPageSize) << ")"
2169       << " #metadata_bytes=" << PrettySize(num_metadata_bytes[i])
2170       << " #slots=" << num_slots[i] << " (" << PrettySize(num_slots[i] * bracketSizes[i]) << ")"
2171       << " #used_slots=" << num_used_slots[i]
2172       << " (" << PrettySize(num_used_slots[i] * bracketSizes[i]) << ")\n";
2173  }
2174  os << "Large #allocations=" << num_large_objects
2175     << " #pages=" << num_pages_large_objects
2176     << " (" << PrettySize(num_pages_large_objects * kPageSize) << ")\n";
2177  size_t total_num_pages = 0;
2178  size_t total_metadata_bytes = 0;
2179  size_t total_allocated_bytes = 0;
2180  for (size_t i = 0; i < kNumOfSizeBrackets; ++i) {
2181    total_num_pages += num_pages_runs[i];
2182    total_metadata_bytes += num_metadata_bytes[i];
2183    total_allocated_bytes += num_used_slots[i] * bracketSizes[i];
2184  }
2185  total_num_pages += num_pages_large_objects;
2186  total_allocated_bytes += num_pages_large_objects * kPageSize;
2187  os << "Total #total_bytes=" << PrettySize(total_num_pages * kPageSize)
2188     << " #metadata_bytes=" << PrettySize(total_metadata_bytes)
2189     << " #used_bytes=" << PrettySize(total_allocated_bytes) << "\n";
2190  os << "\n";
2191}
2192
2193}  // namespace allocator
2194}  // namespace gc
2195}  // namespace art
2196