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 #ifndef ART_RUNTIME_GC_ALLOCATOR_ROSALLOC_INL_H_ 18 #define ART_RUNTIME_GC_ALLOCATOR_ROSALLOC_INL_H_ 19 20 #include "rosalloc.h" 21 22 namespace art { 23 namespace gc { 24 namespace allocator { 25 26 inline ALWAYS_INLINE bool RosAlloc::ShouldCheckZeroMemory() { 27 return kCheckZeroMemory && !is_running_on_memory_tool_; 28 } 29 30 template<bool kThreadSafe> 31 inline ALWAYS_INLINE void* RosAlloc::Alloc(Thread* self, size_t size, size_t* bytes_allocated, 32 size_t* usable_size, 33 size_t* bytes_tl_bulk_allocated) { 34 if (UNLIKELY(size > kLargeSizeThreshold)) { 35 return AllocLargeObject(self, size, bytes_allocated, usable_size, 36 bytes_tl_bulk_allocated); 37 } 38 void* m; 39 if (kThreadSafe) { 40 m = AllocFromRun(self, size, bytes_allocated, usable_size, bytes_tl_bulk_allocated); 41 } else { 42 m = AllocFromRunThreadUnsafe(self, size, bytes_allocated, usable_size, 43 bytes_tl_bulk_allocated); 44 } 45 // Check if the returned memory is really all zero. 46 if (ShouldCheckZeroMemory() && m != nullptr) { 47 uint8_t* bytes = reinterpret_cast<uint8_t*>(m); 48 for (size_t i = 0; i < size; ++i) { 49 DCHECK_EQ(bytes[i], 0); 50 } 51 } 52 return m; 53 } 54 55 inline bool RosAlloc::Run::IsFull() { 56 return free_list_.Size() == 0; 57 } 58 59 inline bool RosAlloc::CanAllocFromThreadLocalRun(Thread* self, size_t size) { 60 if (UNLIKELY(!IsSizeForThreadLocal(size))) { 61 return false; 62 } 63 size_t bracket_size; 64 size_t idx = SizeToIndexAndBracketSize(size, &bracket_size); 65 DCHECK_LT(idx, kNumThreadLocalSizeBrackets); 66 Run* thread_local_run = reinterpret_cast<Run*>(self->GetRosAllocRun(idx)); 67 if (kIsDebugBuild) { 68 // Need the lock to prevent race conditions. 69 MutexLock mu(self, *size_bracket_locks_[idx]); 70 CHECK(non_full_runs_[idx].find(thread_local_run) == non_full_runs_[idx].end()); 71 CHECK(full_runs_[idx].find(thread_local_run) == full_runs_[idx].end()); 72 } 73 DCHECK(thread_local_run != nullptr); 74 DCHECK(thread_local_run->IsThreadLocal() || thread_local_run == dedicated_full_run_); 75 return !thread_local_run->IsFull(); 76 } 77 78 inline void* RosAlloc::AllocFromThreadLocalRun(Thread* self, size_t size, 79 size_t* bytes_allocated) { 80 DCHECK(bytes_allocated != nullptr); 81 if (UNLIKELY(!IsSizeForThreadLocal(size))) { 82 return nullptr; 83 } 84 size_t bracket_size; 85 size_t idx = SizeToIndexAndBracketSize(size, &bracket_size); 86 Run* thread_local_run = reinterpret_cast<Run*>(self->GetRosAllocRun(idx)); 87 if (kIsDebugBuild) { 88 // Need the lock to prevent race conditions. 89 MutexLock mu(self, *size_bracket_locks_[idx]); 90 CHECK(non_full_runs_[idx].find(thread_local_run) == non_full_runs_[idx].end()); 91 CHECK(full_runs_[idx].find(thread_local_run) == full_runs_[idx].end()); 92 } 93 DCHECK(thread_local_run != nullptr); 94 DCHECK(thread_local_run->IsThreadLocal() || thread_local_run == dedicated_full_run_); 95 void* slot_addr = thread_local_run->AllocSlot(); 96 if (LIKELY(slot_addr != nullptr)) { 97 *bytes_allocated = bracket_size; 98 } 99 return slot_addr; 100 } 101 102 inline size_t RosAlloc::MaxBytesBulkAllocatedFor(size_t size) { 103 if (UNLIKELY(!IsSizeForThreadLocal(size))) { 104 return size; 105 } 106 size_t bracket_size; 107 size_t idx = SizeToIndexAndBracketSize(size, &bracket_size); 108 return numOfSlots[idx] * bracket_size; 109 } 110 111 inline void* RosAlloc::Run::AllocSlot() { 112 Slot* slot = free_list_.Remove(); 113 if (kTraceRosAlloc && slot != nullptr) { 114 const uint8_t idx = size_bracket_idx_; 115 LOG(INFO) << "RosAlloc::Run::AllocSlot() : " << slot 116 << ", bracket_size=" << std::dec << bracketSizes[idx] 117 << ", slot_idx=" << SlotIndex(slot); 118 } 119 return slot; 120 } 121 122 } // namespace allocator 123 } // namespace gc 124 } // namespace art 125 126 #endif // ART_RUNTIME_GC_ALLOCATOR_ROSALLOC_INL_H_ 127