blob: aa542db6ec8eb56a1913ebb9932eb169be91d2f2 [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"
Carl Shapiro69759ea2011-07-21 18:13:35 -070027
28namespace art {
29
30class Object;
31
32// <offset> is the difference from .base to a pointer address.
33// <index> is the index of .bits that contains the bit representing
34// <offset>.
35#define HB_OFFSET_TO_INDEX(offset_) \
36 ((offset_) / kAlignment / kBitsPerWord)
37#define HB_INDEX_TO_OFFSET(index_) \
38 ((index_) * kAlignment * kBitsPerWord)
39
40#define HB_OFFSET_TO_BYTE_INDEX(offset_) \
Elliott Hughesb0663112011-10-19 18:16:37 -070041 (HB_OFFSET_TO_INDEX(offset_) * sizeof(*(reinterpret_cast<HeapBitmap*>(0))->words_))
Carl Shapiro69759ea2011-07-21 18:13:35 -070042
43// Pack the bits in backwards so they come out in address order
44// when using CLZ.
45#define HB_OFFSET_TO_MASK(offset_) \
Elliott Hughesb0663112011-10-19 18:16:37 -070046 (1 << (31-(((uintptr_t)(offset_) / kAlignment) % kBitsPerWord)))
Carl Shapiro69759ea2011-07-21 18:13:35 -070047
48class HeapBitmap {
49 public:
50 static const size_t kAlignment = 8;
51
Brian Carlstrom78128a62011-09-15 17:21:19 -070052 typedef void Callback(Object* obj, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -070053
Brian Carlstrom78128a62011-09-15 17:21:19 -070054 typedef void ScanCallback(Object* obj, void* finger, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -070055
Ian Rogers30fab402012-01-23 15:43:46 -080056 typedef void SweepCallback(size_t numPtrs, Object** ptrs, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -070057
Ian Rogers30fab402012-01-23 15:43:46 -080058 // Initialize a HeapBitmap so that it points to a bitmap large enough to cover a heap at
59 // heap_begin of heap_capacity bytes, where objects are guaranteed to be kAlignment-aligned.
60 static HeapBitmap* Create(const char* name, byte* heap_begin, size_t heap_capacity);
Carl Shapiro69759ea2011-07-21 18:13:35 -070061
62 ~HeapBitmap();
63
Elliott Hughesb0663112011-10-19 18:16:37 -070064 inline void Set(const Object* obj) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070065 Modify(obj, true);
66 }
67
Elliott Hughesb0663112011-10-19 18:16:37 -070068 inline void Clear(const Object* obj) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070069 Modify(obj, false);
70 }
71
72 void Clear();
73
Elliott Hughesb0663112011-10-19 18:16:37 -070074 inline bool Test(const Object* obj) {
75 uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
76 DCHECK(HasAddress(obj)) << obj;
Ian Rogers30fab402012-01-23 15:43:46 -080077 DCHECK(bitmap_begin_ != NULL);
78 DCHECK_GE(addr, heap_begin_);
79 if (addr <= heap_end_) {
80 const uintptr_t offset = addr - heap_begin_;
81 return (bitmap_begin_[HB_OFFSET_TO_INDEX(offset)] & HB_OFFSET_TO_MASK(offset)) != 0;
Carl Shapiro69759ea2011-07-21 18:13:35 -070082 } else {
Elliott Hughesb0663112011-10-19 18:16:37 -070083 return false;
Carl Shapiro69759ea2011-07-21 18:13:35 -070084 }
85 }
86
87 bool HasAddress(const void* addr) const;
88
Ian Rogers5d76c432011-10-31 21:42:49 -070089 void VisitRange(uintptr_t base, uintptr_t max, Callback* visitor, void* arg) const;
90
Carl Shapiro69759ea2011-07-21 18:13:35 -070091 void Walk(Callback* callback, void* arg);
92
Ian Rogers5d76c432011-10-31 21:42:49 -070093 void ScanWalk(uintptr_t base, uintptr_t max, ScanCallback* thunk, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -070094
95 static void SweepWalk(const HeapBitmap& live,
96 const HeapBitmap& mark,
97 uintptr_t base, uintptr_t max,
98 SweepCallback* thunk, void* arg);
99
100 private:
Ian Rogers30fab402012-01-23 15:43:46 -0800101 // TODO: heap_end_ is initialized so that the heap bitmap is empty, this doesn't require the -1,
102 // however, we document that this is expected on heap_end_
103 HeapBitmap(const char* name, MemMap* mem_map, word* bitmap_begin, size_t bitmap_size, const void* heap_begin)
104 : mem_map_(mem_map), bitmap_begin_(bitmap_begin), bitmap_size_(bitmap_size),
105 heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)), heap_end_(heap_begin_ - 1),
106 name_(name) {}
Carl Shapiro69759ea2011-07-21 18:13:35 -0700107
Elliott Hughesb0663112011-10-19 18:16:37 -0700108 inline void Modify(const Object* obj, bool do_set) {
Carl Shapiro69759ea2011-07-21 18:13:35 -0700109 uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
Ian Rogers30fab402012-01-23 15:43:46 -0800110 DCHECK_GE(addr, heap_begin_);
111 const uintptr_t offset = addr - heap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700112 const size_t index = HB_OFFSET_TO_INDEX(offset);
Elliott Hughesb0663112011-10-19 18:16:37 -0700113 const word mask = HB_OFFSET_TO_MASK(offset);
Ian Rogers30fab402012-01-23 15:43:46 -0800114 DCHECK_LT(index, bitmap_size_ / kWordSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700115 if (do_set) {
Ian Rogers30fab402012-01-23 15:43:46 -0800116 if (addr > heap_end_) {
117 heap_end_ = addr;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700118 }
Ian Rogers30fab402012-01-23 15:43:46 -0800119 bitmap_begin_[index] |= mask;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700120 } else {
Ian Rogers30fab402012-01-23 15:43:46 -0800121 bitmap_begin_[index] &= ~mask;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700122 }
123 }
124
Ian Rogers30fab402012-01-23 15:43:46 -0800125 // Backing storage for bitmap.
Elliott Hughes90a33692011-08-30 13:27:07 -0700126 UniquePtr<MemMap> mem_map_;
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700127
Ian Rogers30fab402012-01-23 15:43:46 -0800128 // This bitmap itself, word sized for efficiency in scanning.
129 word* const bitmap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700130
Ian Rogers30fab402012-01-23 15:43:46 -0800131 // Size of this bitmap.
132 const size_t bitmap_size_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700133
Ian Rogers30fab402012-01-23 15:43:46 -0800134 // The base address of the heap, which corresponds to the word containing the first bit in the
135 // bitmap.
136 const uintptr_t heap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700137
138 // The highest pointer value ever returned by an allocation from
139 // this heap. I.e., the highest address that may correspond to a
Ian Rogers30fab402012-01-23 15:43:46 -0800140 // set bit. If there are no bits set, (heap_end_ < heap_begin_).
141 uintptr_t heap_end_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700142
Ian Rogers30fab402012-01-23 15:43:46 -0800143 // Name of this bitmap.
144 const char* const name_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700145};
146
147} // namespace art
148
Elliott Hughes5e71b522011-10-20 13:12:32 -0700149#endif // ART_SRC_HEAP_BITMAP_H_