blob: 70684b9b2075809bdb5b297cb794adb1de564893 [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 Rogers1351b672012-02-24 12:22:57 -080093 void InOrderWalk(HeapBitmap::Callback* callback, void* arg);
94
Ian Rogers5d76c432011-10-31 21:42:49 -070095 void ScanWalk(uintptr_t base, uintptr_t max, ScanCallback* thunk, void* arg);
Carl Shapiro69759ea2011-07-21 18:13:35 -070096
97 static void SweepWalk(const HeapBitmap& live,
98 const HeapBitmap& mark,
99 uintptr_t base, uintptr_t max,
100 SweepCallback* thunk, void* arg);
101
102 private:
Ian Rogers30fab402012-01-23 15:43:46 -0800103 // TODO: heap_end_ is initialized so that the heap bitmap is empty, this doesn't require the -1,
104 // however, we document that this is expected on heap_end_
105 HeapBitmap(const char* name, MemMap* mem_map, word* bitmap_begin, size_t bitmap_size, const void* heap_begin)
106 : mem_map_(mem_map), bitmap_begin_(bitmap_begin), bitmap_size_(bitmap_size),
107 heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)), heap_end_(heap_begin_ - 1),
108 name_(name) {}
Carl Shapiro69759ea2011-07-21 18:13:35 -0700109
Elliott Hughesb0663112011-10-19 18:16:37 -0700110 inline void Modify(const Object* obj, bool do_set) {
Carl Shapiro69759ea2011-07-21 18:13:35 -0700111 uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
Ian Rogers30fab402012-01-23 15:43:46 -0800112 DCHECK_GE(addr, heap_begin_);
113 const uintptr_t offset = addr - heap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700114 const size_t index = HB_OFFSET_TO_INDEX(offset);
Elliott Hughesb0663112011-10-19 18:16:37 -0700115 const word mask = HB_OFFSET_TO_MASK(offset);
Ian Rogers30fab402012-01-23 15:43:46 -0800116 DCHECK_LT(index, bitmap_size_ / kWordSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700117 if (do_set) {
Ian Rogers30fab402012-01-23 15:43:46 -0800118 if (addr > heap_end_) {
119 heap_end_ = addr;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700120 }
Ian Rogers30fab402012-01-23 15:43:46 -0800121 bitmap_begin_[index] |= mask;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700122 } else {
Ian Rogers30fab402012-01-23 15:43:46 -0800123 bitmap_begin_[index] &= ~mask;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700124 }
125 }
126
Ian Rogers30fab402012-01-23 15:43:46 -0800127 // Backing storage for bitmap.
Elliott Hughes90a33692011-08-30 13:27:07 -0700128 UniquePtr<MemMap> mem_map_;
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700129
Ian Rogers30fab402012-01-23 15:43:46 -0800130 // This bitmap itself, word sized for efficiency in scanning.
131 word* const bitmap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700132
Ian Rogers30fab402012-01-23 15:43:46 -0800133 // Size of this bitmap.
134 const size_t bitmap_size_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700135
Ian Rogers30fab402012-01-23 15:43:46 -0800136 // The base address of the heap, which corresponds to the word containing the first bit in the
137 // bitmap.
138 const uintptr_t heap_begin_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700139
140 // The highest pointer value ever returned by an allocation from
141 // this heap. I.e., the highest address that may correspond to a
Ian Rogers30fab402012-01-23 15:43:46 -0800142 // set bit. If there are no bits set, (heap_end_ < heap_begin_).
143 uintptr_t heap_end_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700144
Ian Rogers30fab402012-01-23 15:43:46 -0800145 // Name of this bitmap.
146 const char* const name_;
Carl Shapiro69759ea2011-07-21 18:13:35 -0700147};
148
149} // namespace art
150
Elliott Hughes5e71b522011-10-20 13:12:32 -0700151#endif // ART_SRC_HEAP_BITMAP_H_