1 /* 2 * Copyright (C) 2008 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_ACCOUNTING_SPACE_BITMAP_H_ 18 #define ART_RUNTIME_GC_ACCOUNTING_SPACE_BITMAP_H_ 19 20 #include <limits.h> 21 #include <stdint.h> 22 #include <memory> 23 #include <set> 24 #include <vector> 25 26 #include "base/mutex.h" 27 #include "globals.h" 28 #include "object_callbacks.h" 29 30 namespace art { 31 32 namespace mirror { 33 class Class; 34 class Object; 35 } // namespace mirror 36 class MemMap; 37 38 namespace gc { 39 namespace accounting { 40 41 template<size_t kAlignment> 42 class SpaceBitmap { 43 public: 44 typedef void ScanCallback(mirror::Object* obj, void* finger, void* arg); 45 typedef void SweepCallback(size_t ptr_count, mirror::Object** ptrs, void* arg); 46 47 // Initialize a space bitmap so that it points to a bitmap large enough to cover a heap at 48 // heap_begin of heap_capacity bytes, where objects are guaranteed to be kAlignment-aligned. 49 static SpaceBitmap* Create(const std::string& name, uint8_t* heap_begin, size_t heap_capacity); 50 51 // Initialize a space bitmap using the provided mem_map as the live bits. Takes ownership of the 52 // mem map. The address range covered starts at heap_begin and is of size equal to heap_capacity. 53 // Objects are kAlignement-aligned. 54 static SpaceBitmap* CreateFromMemMap(const std::string& name, MemMap* mem_map, 55 uint8_t* heap_begin, size_t heap_capacity); 56 57 ~SpaceBitmap(); 58 59 // <offset> is the difference from .base to a pointer address. 60 // <index> is the index of .bits that contains the bit representing 61 // <offset>. OffsetToIndex(size_t offset)62 static constexpr size_t OffsetToIndex(size_t offset) { 63 return offset / kAlignment / kBitsPerIntPtrT; 64 } 65 66 template<typename T> IndexToOffset(T index)67 static constexpr T IndexToOffset(T index) { 68 return static_cast<T>(index * kAlignment * kBitsPerIntPtrT); 69 } 70 OffsetBitIndex(uintptr_t offset)71 ALWAYS_INLINE static constexpr uintptr_t OffsetBitIndex(uintptr_t offset) { 72 return (offset / kAlignment) % kBitsPerIntPtrT; 73 } 74 75 // Bits are packed in the obvious way. OffsetToMask(uintptr_t offset)76 static constexpr uintptr_t OffsetToMask(uintptr_t offset) { 77 return static_cast<size_t>(1) << OffsetBitIndex(offset); 78 } 79 Set(const mirror::Object * obj)80 bool Set(const mirror::Object* obj) ALWAYS_INLINE { 81 return Modify<true>(obj); 82 } 83 Clear(const mirror::Object * obj)84 bool Clear(const mirror::Object* obj) ALWAYS_INLINE { 85 return Modify<false>(obj); 86 } 87 88 // Returns true if the object was previously marked. 89 bool AtomicTestAndSet(const mirror::Object* obj); 90 91 // Fill the bitmap with zeroes. Returns the bitmap's memory to the system as a side-effect. 92 void Clear(); 93 94 // Clear a covered by the bitmap using madvise if possible. 95 void ClearRange(const mirror::Object* begin, const mirror::Object* end); 96 97 bool Test(const mirror::Object* obj) const; 98 99 // Return true iff <obj> is within the range of pointers that this bitmap could potentially cover, 100 // even if a bit has not been set for it. HasAddress(const void * obj)101 bool HasAddress(const void* obj) const { 102 // If obj < heap_begin_ then offset underflows to some very large value past the end of the 103 // bitmap. 104 const uintptr_t offset = reinterpret_cast<uintptr_t>(obj) - heap_begin_; 105 const size_t index = OffsetToIndex(offset); 106 return index < bitmap_size_ / sizeof(intptr_t); 107 } 108 109 void VisitRange(uintptr_t base, uintptr_t max, ObjectCallback* callback, void* arg) const; 110 111 class ClearVisitor { 112 public: ClearVisitor(SpaceBitmap * const bitmap)113 explicit ClearVisitor(SpaceBitmap* const bitmap) 114 : bitmap_(bitmap) { 115 } 116 operator()117 void operator()(mirror::Object* obj) const { 118 bitmap_->Clear(obj); 119 } 120 private: 121 SpaceBitmap* const bitmap_; 122 }; 123 124 template <typename Visitor> VisitRange(uintptr_t visit_begin,uintptr_t visit_end,const Visitor & visitor)125 void VisitRange(uintptr_t visit_begin, uintptr_t visit_end, const Visitor& visitor) const { 126 for (; visit_begin < visit_end; visit_begin += kAlignment) { 127 visitor(reinterpret_cast<mirror::Object*>(visit_begin)); 128 } 129 } 130 131 // Visit the live objects in the range [visit_begin, visit_end). 132 // TODO: Use lock annotations when clang is fixed. 133 // REQUIRES(Locks::heap_bitmap_lock_) REQUIRES_SHARED(Locks::mutator_lock_); 134 template <typename Visitor> 135 void VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end, const Visitor& visitor) const 136 NO_THREAD_SAFETY_ANALYSIS; 137 138 // Visits set bits in address order. The callback is not permitted to change the bitmap bits or 139 // max during the traversal. 140 void Walk(ObjectCallback* callback, void* arg) 141 REQUIRES_SHARED(Locks::heap_bitmap_lock_); 142 143 // Walk through the bitmaps in increasing address order, and find the object pointers that 144 // correspond to garbage objects. Call <callback> zero or more times with lists of these object 145 // pointers. The callback is not permitted to increase the max of either bitmap. 146 static void SweepWalk(const SpaceBitmap& live, const SpaceBitmap& mark, uintptr_t base, 147 uintptr_t max, SweepCallback* thunk, void* arg); 148 149 void CopyFrom(SpaceBitmap* source_bitmap); 150 151 // Starting address of our internal storage. Begin()152 Atomic<uintptr_t>* Begin() { 153 return bitmap_begin_; 154 } 155 156 // Size of our internal storage Size()157 size_t Size() const { 158 return bitmap_size_; 159 } 160 161 // Size in bytes of the memory that the bitmaps spans. HeapSize()162 uint64_t HeapSize() const { 163 return IndexToOffset<uint64_t>(Size() / sizeof(intptr_t)); 164 } 165 SetHeapSize(size_t bytes)166 void SetHeapSize(size_t bytes) { 167 // TODO: Un-map the end of the mem map. 168 bitmap_size_ = OffsetToIndex(bytes) * sizeof(intptr_t); 169 CHECK_EQ(HeapSize(), bytes); 170 } 171 HeapBegin()172 uintptr_t HeapBegin() const { 173 return heap_begin_; 174 } 175 176 // The maximum address which the bitmap can span. (HeapBegin() <= object < HeapLimit()). HeapLimit()177 uint64_t HeapLimit() const { 178 return static_cast<uint64_t>(HeapBegin()) + HeapSize(); 179 } 180 181 // Set the max address which can covered by the bitmap. 182 void SetHeapLimit(uintptr_t new_end); 183 GetName()184 std::string GetName() const { 185 return name_; 186 } 187 SetName(const std::string & name)188 void SetName(const std::string& name) { 189 name_ = name; 190 } 191 192 std::string Dump() const; 193 194 // Helper function for computing bitmap size based on a 64 bit capacity. 195 static size_t ComputeBitmapSize(uint64_t capacity); 196 static size_t ComputeHeapSize(uint64_t bitmap_bytes); 197 198 private: 199 // TODO: heap_end_ is initialized so that the heap bitmap is empty, this doesn't require the -1, 200 // however, we document that this is expected on heap_end_ 201 SpaceBitmap(const std::string& name, MemMap* mem_map, uintptr_t* bitmap_begin, size_t bitmap_size, 202 const void* heap_begin); 203 204 template<bool kSetBit> 205 bool Modify(const mirror::Object* obj); 206 207 // Backing storage for bitmap. 208 std::unique_ptr<MemMap> mem_map_; 209 210 // This bitmap itself, word sized for efficiency in scanning. 211 Atomic<uintptr_t>* const bitmap_begin_; 212 213 // Size of this bitmap. 214 size_t bitmap_size_; 215 216 // The base address of the heap, which corresponds to the word containing the first bit in the 217 // bitmap. 218 const uintptr_t heap_begin_; 219 220 // Name of this bitmap. 221 std::string name_; 222 }; 223 224 typedef SpaceBitmap<kObjectAlignment> ContinuousSpaceBitmap; 225 typedef SpaceBitmap<kLargeObjectAlignment> LargeObjectBitmap; 226 227 template<size_t kAlignment> 228 std::ostream& operator << (std::ostream& stream, const SpaceBitmap<kAlignment>& bitmap); 229 230 } // namespace accounting 231 } // namespace gc 232 } // namespace art 233 234 #endif // ART_RUNTIME_GC_ACCOUNTING_SPACE_BITMAP_H_ 235