blob: 34c11b94e74c3773495c3de64bd4e67504e9e8e6 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Carl Shapiro69759ea2011-07-21 18:13:35 -070016
Elliott Hughes5e71b522011-10-20 13:12:32 -070017#ifndef ART_SRC_HEAP_BITMAP_H_
18#define ART_SRC_HEAP_BITMAP_H_
Carl Shapiro69759ea2011-07-21 18:13:35 -070019
20#include <limits.h>
21#include <stdint.h>
22
Elliott Hughes90a33692011-08-30 13:27:07 -070023#include "UniquePtr.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070024#include "globals.h"
25#include "logging.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070026#include "mem_map.h"
Mathieu Chartierb43b7d42012-06-19 13:15:09 -070027#include "utils.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -070028
29namespace art {
30
31class Object;
32
33// <offset> is the difference from .base to a pointer address.
34// <index> is the index of .bits that contains the bit representing
35// <offset>.
36#define HB_OFFSET_TO_INDEX(offset_) \
37 ((offset_) / kAlignment / kBitsPerWord)
38#define HB_INDEX_TO_OFFSET(index_) \
39 ((index_) * kAlignment * kBitsPerWord)
40
41#define HB_OFFSET_TO_BYTE_INDEX(offset_) \
Elliott Hughesb0663112011-10-19 18:16:37 -070042 (HB_OFFSET_TO_INDEX(offset_) * sizeof(*(reinterpret_cast<HeapBitmap*>(0))->words_))
Carl Shapiro69759ea2011-07-21 18:13:35 -070043
44// Pack the bits in backwards so they come out in address order
45// when using CLZ.
46#define HB_OFFSET_TO_MASK(offset_) \
Elliott Hughesb0663112011-10-19 18:16:37 -070047 (1 << (31-(((uintptr_t)(offset_) / kAlignment) % kBitsPerWord)))
Carl Shapiro69759ea2011-07-21 18:13:35 -070048
49class HeapBitmap {
50 public:
51 static const size_t kAlignment = 8;
52
Brian Carlstrom78128a62011-09-15 17:21:19 -070053 typedef void Callback(Object* obj, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -070054
Brian Carlstrom78128a62011-09-15 17:21:19 -070055 typedef void ScanCallback(Object* obj, void* finger, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -070056
Elliott Hughes24edeb52012-06-18 15:29:46 -070057 typedef void SweepCallback(size_t ptr_count, Object** ptrs, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -070058
Ian Rogers30fab402012-01-23 15:43:46 -080059 // Initialize a HeapBitmap so that it points to a bitmap large enough to cover a heap at
60 // heap_begin of heap_capacity bytes, where objects are guaranteed to be kAlignment-aligned.
61 static HeapBitmap* Create(const char* name, byte* heap_begin, size_t heap_capacity);
Carl Shapiro69759ea2011-07-21 18:13:35 -070062
63 ~HeapBitmap();
64
Elliott Hughesb0663112011-10-19 18:16:37 -070065 inline void Set(const Object* obj) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070066 Modify(obj, true);
67 }
68
Elliott Hughesb0663112011-10-19 18:16:37 -070069 inline void Clear(const Object* obj) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070070 Modify(obj, false);
71 }
72
73 void Clear();
74
Elliott Hughesb0663112011-10-19 18:16:37 -070075 inline bool Test(const Object* obj) {
76 uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
77 DCHECK(HasAddress(obj)) << obj;
Ian Rogers30fab402012-01-23 15:43:46 -080078 DCHECK(bitmap_begin_ != NULL);
79 DCHECK_GE(addr, heap_begin_);
80 if (addr <= heap_end_) {
81 const uintptr_t offset = addr - heap_begin_;
82 return (bitmap_begin_[HB_OFFSET_TO_INDEX(offset)] & HB_OFFSET_TO_MASK(offset)) != 0;
Carl Shapiro69759ea2011-07-21 18:13:35 -070083 } else {
Elliott Hughesb0663112011-10-19 18:16:37 -070084 return false;
Carl Shapiro69759ea2011-07-21 18:13:35 -070085 }
86 }
87
88 bool HasAddress(const void* addr) const;
89
Ian Rogers5d76c432011-10-31 21:42:49 -070090 void VisitRange(uintptr_t base, uintptr_t max, Callback* visitor, void* arg) const;
91
Mathieu Chartierb43b7d42012-06-19 13:15:09 -070092 class ClearVisitor {
93 public:
94 explicit ClearVisitor(HeapBitmap* const bitmap)
95 : bitmap_(bitmap) {
96 }
97
98 void operator ()(Object* obj) const {
99 bitmap_->Clear(obj);
100 }
101 private:
102 HeapBitmap* const bitmap_;
103 };
104
105 template <typename Visitor>
106 void VisitRange(uintptr_t visit_begin, uintptr_t visit_end, const Visitor& visitor) const {
107 for (; visit_begin < visit_end; visit_begin += kAlignment ) {
108 visitor(reinterpret_cast<Object*>(visit_begin));
109 }
110 }
111
112 template <typename Visitor>
113 void VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end, const Visitor& visitor) const {
114 size_t start = HB_OFFSET_TO_INDEX(visit_begin - heap_begin_);
115 size_t end = HB_OFFSET_TO_INDEX(visit_end - heap_begin_ - 1);
116 for (size_t i = start; i <= end; i++) {
117 word w = bitmap_begin_[i];
118 if (w != 0) {
119 word high_bit = 1 << (kBitsPerWord - 1);
120 uintptr_t ptr_base = HB_INDEX_TO_OFFSET(i) + heap_begin_;
121 do {
122 const int shift = CLZ(w);
123 Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment);
124 visitor(obj);
125 w &= ~(high_bit >> shift);
126 } while (w != 0);
127 }
128 }
129 }
130
Carl Shapiro69759ea2011-07-21 18:13:35 -0700131 void Walk(Callback* callback, void* arg);
132
Ian Rogers1351b672012-02-24 12:22:57 -0800133 void InOrderWalk(HeapBitmap::Callback* callback, void* arg);
134
Ian Rogers5d76c432011-10-31 21:42:49 -0700135 void ScanWalk(uintptr_t base, uintptr_t max, ScanCallback* thunk, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700136
137 static void SweepWalk(const HeapBitmap& live,
138 const HeapBitmap& mark,
139 uintptr_t base, uintptr_t max,
140 SweepCallback* thunk, void* arg);
141
142 private:
Ian Rogers30fab402012-01-23 15:43:46 -0800143 // TODO: heap_end_ is initialized so that the heap bitmap is empty, this doesn't require the -1,
144 // however, we document that this is expected on heap_end_
145 HeapBitmap(const char* name, MemMap* mem_map, word* bitmap_begin, size_t bitmap_size, const void* heap_begin)
146 : mem_map_(mem_map), bitmap_begin_(bitmap_begin), bitmap_size_(bitmap_size),
147 heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)), heap_end_(heap_begin_ - 1),
148 name_(name) {}
Carl Shapiro69759ea2011-07-21 18:13:35 -0700149
Elliott Hughesb0663112011-10-19 18:16:37 -0700150 inline void Modify(const Object* obj, bool do_set) {
Carl Shapiro69759ea2011-07-21 18:13:35 -0700151 uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
Ian Rogers30fab402012-01-23 15:43:46 -0800152 DCHECK_GE(addr, heap_begin_);
153 const uintptr_t offset = addr - heap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700154 const size_t index = HB_OFFSET_TO_INDEX(offset);
Elliott Hughesb0663112011-10-19 18:16:37 -0700155 const word mask = HB_OFFSET_TO_MASK(offset);
Ian Rogers30fab402012-01-23 15:43:46 -0800156 DCHECK_LT(index, bitmap_size_ / kWordSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700157 if (do_set) {
Ian Rogers30fab402012-01-23 15:43:46 -0800158 if (addr > heap_end_) {
159 heap_end_ = addr;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700160 }
Ian Rogers30fab402012-01-23 15:43:46 -0800161 bitmap_begin_[index] |= mask;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700162 } else {
Ian Rogers30fab402012-01-23 15:43:46 -0800163 bitmap_begin_[index] &= ~mask;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700164 }
165 }
166
Ian Rogers30fab402012-01-23 15:43:46 -0800167 // Backing storage for bitmap.
Elliott Hughes90a33692011-08-30 13:27:07 -0700168 UniquePtr<MemMap> mem_map_;
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700169
Ian Rogers30fab402012-01-23 15:43:46 -0800170 // This bitmap itself, word sized for efficiency in scanning.
171 word* const bitmap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700172
Ian Rogers30fab402012-01-23 15:43:46 -0800173 // Size of this bitmap.
174 const size_t bitmap_size_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700175
Ian Rogers30fab402012-01-23 15:43:46 -0800176 // The base address of the heap, which corresponds to the word containing the first bit in the
177 // bitmap.
178 const uintptr_t heap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700179
180 // The highest pointer value ever returned by an allocation from
181 // this heap. I.e., the highest address that may correspond to a
Ian Rogers30fab402012-01-23 15:43:46 -0800182 // set bit. If there are no bits set, (heap_end_ < heap_begin_).
183 uintptr_t heap_end_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700184
Ian Rogers30fab402012-01-23 15:43:46 -0800185 // Name of this bitmap.
186 const char* const name_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700187};
188
189} // namespace art
190
Elliott Hughes5e71b522011-10-20 13:12:32 -0700191#endif // ART_SRC_HEAP_BITMAP_H_