blob: 4bd191ac39f5b5e3b83a09392cf66cd2e5799f7c [file] [log] [blame]
Carl Shapiro69759ea2011-07-21 18:13:35 -07001// Copyright (C) 2008 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Elliott Hughes5e71b522011-10-20 13:12:32 -070015#include "heap_bitmap.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -070016
17#include <sys/mman.h>
18
Elliott Hughes90a33692011-08-30 13:27:07 -070019#include "UniquePtr.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070020#include "logging.h"
Brian Carlstrom27ec9612011-09-19 20:20:38 -070021#include "utils.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -070022
23namespace art {
24
Elliott Hughes6c9c06d2011-11-07 16:43:47 -080025HeapBitmap* HeapBitmap::Create(const char* name, byte* base, size_t length) {
Elliott Hughes90a33692011-08-30 13:27:07 -070026 UniquePtr<HeapBitmap> bitmap(new HeapBitmap(base, length));
Elliott Hughes6c9c06d2011-11-07 16:43:47 -080027 if (!bitmap->Init(name, base, length)) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070028 return NULL;
29 } else {
30 return bitmap.release();
31 }
32}
33
34// Initialize a HeapBitmap so that it points to a bitmap large enough
Brian Carlstrom1f870082011-08-23 16:02:11 -070035// to cover a heap at <base> of <max_size> bytes, where objects are
Carl Shapiro69759ea2011-07-21 18:13:35 -070036// guaranteed to be kAlignment-aligned.
Elliott Hughes6c9c06d2011-11-07 16:43:47 -080037bool HeapBitmap::Init(const char* name, const byte* base, size_t max_size) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070038 CHECK(base != NULL);
39 size_t length = HB_OFFSET_TO_INDEX(max_size) * kWordSize;
Elliott Hughes6c9c06d2011-11-07 16:43:47 -080040 mem_map_.reset(MemMap::Map(name, NULL, length, PROT_READ | PROT_WRITE));
Elliott Hughes90a33692011-08-30 13:27:07 -070041 if (mem_map_.get() == NULL) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070042 return false;
43 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -070044 words_ = reinterpret_cast<word*>(mem_map_->GetAddress());
Carl Shapiro69759ea2011-07-21 18:13:35 -070045 num_bytes_ = length;
46 base_ = reinterpret_cast<uintptr_t>(base);
47 max_ = base_ - 1;
48 return true;
49}
50
51// Clean up any resources associated with the bitmap.
Brian Carlstromdb4d5402011-08-09 12:18:28 -070052HeapBitmap::~HeapBitmap() {}
Carl Shapiro69759ea2011-07-21 18:13:35 -070053
54// Fill the bitmap with zeroes. Returns the bitmap's memory to the
55// system as a side-effect.
56void HeapBitmap::Clear() {
57 if (words_ != NULL) {
58 // This returns the memory to the system. Successive page faults
59 // will return zeroed memory.
60 int result = madvise(words_, num_bytes_, MADV_DONTNEED);
61 if (result == -1) {
62 PLOG(WARNING) << "madvise failed";
63 }
64 max_ = base_ - 1;
65 }
66}
67
68// Return true iff <obj> is within the range of pointers that this
69// bitmap could potentially cover, even if a bit has not been set for
70// it.
71bool HeapBitmap::HasAddress(const void* obj) const {
72 if (obj != NULL) {
73 const uintptr_t offset = (uintptr_t)obj - base_;
74 const size_t index = HB_OFFSET_TO_INDEX(offset);
75 return index < num_bytes_ / kWordSize;
76 }
77 return false;
78}
79
Ian Rogers5d76c432011-10-31 21:42:49 -070080void HeapBitmap::VisitRange(uintptr_t base, uintptr_t max, Callback* visitor, void* arg) const {
81 size_t start = HB_OFFSET_TO_INDEX(base - base_);
82 size_t end = HB_OFFSET_TO_INDEX(max - base_ - 1);
83 for (size_t i = start; i <= end; i++) {
84 word w = words_[i];
85 if (w != 0) {
86 word high_bit = 1 << (kBitsPerWord - 1);
87 uintptr_t ptr_base = HB_INDEX_TO_OFFSET(i) + base_;
88 while (w != 0) {
89 const int shift = CLZ(w);
90 Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment);
91 (*visitor)(obj, arg);
92 w &= ~(high_bit >> shift);
93 }
94 }
95 }
96}
97
Carl Shapiro69759ea2011-07-21 18:13:35 -070098// Visits set bits in address order. The callback is not permitted to
99// change the bitmap bits or max during the traversal.
100void HeapBitmap::Walk(HeapBitmap::Callback* callback, void* arg) {
101 CHECK(words_ != NULL);
102 CHECK(callback != NULL);
103 uintptr_t end = HB_OFFSET_TO_INDEX(max_ - base_);
104 for (uintptr_t i = 0; i <= end; ++i) {
Elliott Hughesb0663112011-10-19 18:16:37 -0700105 word w = words_[i];
106 if (UNLIKELY(w != 0)) {
107 word high_bit = 1 << (kBitsPerWord - 1);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700108 uintptr_t ptr_base = HB_INDEX_TO_OFFSET(i) + base_;
Elliott Hughesb0663112011-10-19 18:16:37 -0700109 while (w != 0) {
110 const int shift = CLZ(w);
111 Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700112 (*callback)(obj, arg);
Elliott Hughesb0663112011-10-19 18:16:37 -0700113 w &= ~(high_bit >> shift);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700114 }
115 }
116 }
117}
118
119// Similar to Walk but the callback routine is permitted to change the
120// bitmap bits and max during traversal. Used by the the root marking
121// scan exclusively.
122//
123// The callback is invoked with a finger argument. The finger is a
124// pointer to an address not yet visited by the traversal. If the
125// callback sets a bit for an address at or above the finger, this
126// address will be visited by the traversal. If the callback sets a
127// bit for an address below the finger, this address will not be
128// visited.
Ian Rogers5d76c432011-10-31 21:42:49 -0700129void HeapBitmap::ScanWalk(uintptr_t base, uintptr_t max, ScanCallback* callback, void* arg) {
130 CHECK(words_ != NULL);
131 CHECK(callback != NULL);
132 CHECK_LE(base, max);
133 CHECK_GE(base, base_);
134 size_t start = HB_OFFSET_TO_INDEX(base - base_);
135 if (max < max_) {
136 // The end of the space we're looking at is before the current maximum bitmap PC, scan to that
137 // and don't recompute end on each iteration
138 size_t end = HB_OFFSET_TO_INDEX(max - base_ - 1);
139 for (size_t i = start; i <= end; i++) {
140 word w = words_[i];
141 if (UNLIKELY(w != 0)) {
142 word high_bit = 1 << (kBitsPerWord - 1);
143 uintptr_t ptr_base = HB_INDEX_TO_OFFSET(i) + base_;
144 void* finger = reinterpret_cast<void*>(HB_INDEX_TO_OFFSET(i + 1) + base_);
145 while (w != 0) {
146 const int shift = CLZ(w);
147 Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment);
148 (*callback)(obj, finger, arg);
149 w &= ~(high_bit >> shift);
150 }
151 }
152 }
153 } else {
154 size_t end = HB_OFFSET_TO_INDEX(max_ - base_);
155 for (size_t i = start; i <= end; i++) {
156 word w = words_[i];
157 if (UNLIKELY(w != 0)) {
158 word high_bit = 1 << (kBitsPerWord - 1);
159 uintptr_t ptr_base = HB_INDEX_TO_OFFSET(i) + base_;
160 void* finger = reinterpret_cast<void*>(HB_INDEX_TO_OFFSET(i + 1) + base_);
161 while (w != 0) {
162 const int shift = CLZ(w);
163 Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment);
164 (*callback)(obj, finger, arg);
165 w &= ~(high_bit >> shift);
166 }
Carl Shapiro69759ea2011-07-21 18:13:35 -0700167 }
168 end = HB_OFFSET_TO_INDEX(max_ - base_);
169 }
170 }
171}
172
173// Walk through the bitmaps in increasing address order, and find the
174// object pointers that correspond to garbage objects. Call
175// <callback> zero or more times with lists of these object pointers.
176//
177// The callback is not permitted to increase the max of either bitmap.
178void HeapBitmap::SweepWalk(const HeapBitmap& live_bitmap,
179 const HeapBitmap& mark_bitmap,
180 uintptr_t base, uintptr_t max,
181 HeapBitmap::SweepCallback* callback, void* arg) {
182 CHECK(live_bitmap.words_ != NULL);
183 CHECK(mark_bitmap.words_ != NULL);
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700184 CHECK_EQ(live_bitmap.base_, mark_bitmap.base_);
185 CHECK_EQ(live_bitmap.num_bytes_, mark_bitmap.num_bytes_);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700186 CHECK(callback != NULL);
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700187 CHECK_LE(base, max);
188 CHECK_GE(base, live_bitmap.base_);
Ian Rogers5d76c432011-10-31 21:42:49 -0700189 max = std::min(max - 1, live_bitmap.max_);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700190 if (live_bitmap.max_ < live_bitmap.base_) {
191 // Easy case; both are obviously empty.
192 // TODO: this should never happen
193 return;
194 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700195 // TODO: rewrite the callbacks to accept a std::vector<void*> rather than a void**?
196 std::vector<void*> pointer_buf(4 * kBitsPerWord);
197 void** pb = &pointer_buf[0];
Carl Shapiro69759ea2011-07-21 18:13:35 -0700198 size_t start = HB_OFFSET_TO_INDEX(base - live_bitmap.base_);
199 size_t end = HB_OFFSET_TO_INDEX(max - live_bitmap.base_);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700200 word* live = live_bitmap.words_;
201 word* mark = mark_bitmap.words_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700202 for (size_t i = start; i <= end; i++) {
Elliott Hughesb0663112011-10-19 18:16:37 -0700203 word garbage = live[i] & ~mark[i];
204 if (UNLIKELY(garbage != 0)) {
205 word high_bit = 1 << (kBitsPerWord - 1);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700206 uintptr_t ptr_base = HB_INDEX_TO_OFFSET(i) + live_bitmap.base_;
207 while (garbage != 0) {
208 int shift = CLZ(garbage);
209 garbage &= ~(high_bit >> shift);
Elliott Hughesb0663112011-10-19 18:16:37 -0700210 *pb++ = reinterpret_cast<void*>(ptr_base + shift * kAlignment);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700211 }
212 // Make sure that there are always enough slots available for an
213 // entire word of one bits.
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700214 if (pb >= &pointer_buf[pointer_buf.size() - kBitsPerWord]) {
215 (*callback)(pb - &pointer_buf[0], &pointer_buf[0], arg);
216 pb = &pointer_buf[0];
Carl Shapiro69759ea2011-07-21 18:13:35 -0700217 }
218 }
219 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700220 if (pb > &pointer_buf[0]) {
221 (*callback)(pb - &pointer_buf[0], &pointer_buf[0], arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700222 }
223}
224
225} // namespace art