blob: c73dd6b7bb548f381a1d29de2df5e1804cbae99e [file] [log] [blame]
Mathieu Chartierb43b7d42012-06-19 13:15:09 -07001/*
2 * Copyright (C) 2012 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#include "heap.h"
18#include "heap_bitmap.h"
19#include "mark_sweep.h"
20#include "mod_union_table.h"
21#include "space.h"
22#include "stl_util.h"
23#include "UniquePtr.h"
24
25namespace art {
26
27class MarkIfReachesAllocspaceVisitor {
28 public:
29 explicit MarkIfReachesAllocspaceVisitor(MarkSweep* const mark_sweep, HeapBitmap* bitmap)
30 : mark_sweep_(mark_sweep),
31 bitmap_(bitmap) {
32 }
33
34 // Extra parameters are required since we use this same visitor signature for checking objects.
35 void operator ()(const Object* obj, const Object* ref, MemberOffset offset, bool is_static) const {
36 if (mark_sweep_->heap_->GetAllocSpace()->Contains(ref)) {
37 // This can mark the same object multiple times, but is unlikely to be a performance problem.
38 bitmap_->Set(obj);
39 }
40 // Avoid warnings.
41 (void)obj;(void)offset;(void)is_static;
42 }
43
44 private:
45 MarkSweep* const mark_sweep_;
46 HeapBitmap* bitmap_;
47};
48
49class ModUnionVisitor {
50 public:
51 explicit ModUnionVisitor(MarkSweep* const mark_sweep, HeapBitmap* bitmap)
52 : mark_sweep_(mark_sweep),
53 bitmap_(bitmap) {
54 }
55
56 void operator ()(Object* obj) const {
57 DCHECK(obj != NULL);
58 // We don't have an early exit since we use the visitor pattern, an early
59 // exit should significantly speed this up.
60 MarkIfReachesAllocspaceVisitor visitor(mark_sweep_, bitmap_);
61 mark_sweep_->VisitObjectReferences(obj, visitor);
62 }
63 private:
64 MarkSweep* const mark_sweep_;
65 HeapBitmap* bitmap_;
66};
67
68class ModUnionClearCardVisitor {
69 public:
70 explicit ModUnionClearCardVisitor(std::vector<byte*>* cleared_cards)
71 : cleared_cards_(cleared_cards) {
72 }
73
74 void operator ()(byte* card) const {
75 cleared_cards_->push_back(card);
76 }
77 private:
78 std::vector<byte*>* cleared_cards_;
79};
80
81ModUnionTableBitmap::ModUnionTableBitmap(Heap* heap) : heap_(heap) {
82 // Prevent fragmentation of the heap which is caused by resizing of the vector.
83 // TODO: Make a new vector which uses madvise (basically same as a mark stack).
84 cleared_cards_.reserve(4 * KB);
85}
86
87ModUnionTableBitmap::~ModUnionTableBitmap() {
88 STLDeleteValues(&bitmaps_);
89}
90
91void ModUnionTableBitmap::Init() {
92 const std::vector<Space*>& spaces = heap_->GetSpaces();
93
94 // Create one heap bitmap per image space.
95 for (size_t i = 0; i < spaces.size(); ++i) {
96 if (spaces[i]->IsImageSpace()) {
97 // Allocate the mod-union table
98 // The mod-union table is only needed when we have an image space since it's purpose is to cache image roots.
99 UniquePtr<HeapBitmap> bitmap(HeapBitmap::Create("mod-union table bitmap", spaces[i]->Begin(), spaces[i]->Capacity()));
100 if (bitmap.get() == NULL) {
101 LOG(FATAL) << "Failed to create mod-union bitmap";
102 }
103
104 bitmaps_.Put(spaces[i], bitmap.release());
105 }
106 }
107}
108
109void ModUnionTableBitmap::ClearCards() {
110 CardTable* card_table = heap_->GetCardTable();
111 for (BitmapMap::iterator cur = bitmaps_.begin(); cur != bitmaps_.end(); ++cur) {
112 const Space* space = cur->first;
113 ModUnionClearCardVisitor visitor(&cleared_cards_);
114 // Clear dirty cards in the this image space and update the corresponding mod-union bits.
115 card_table->VisitClear(space->Begin(), space->End(), visitor);
116 }
117}
118
119void ModUnionTableBitmap::Update(MarkSweep* mark_sweep) {
120 CardTable* card_table = heap_->GetCardTable();
121
122 while (!cleared_cards_.empty()) {
123 byte* card = cleared_cards_.back();
124 cleared_cards_.pop_back();
125
126 // Find out which bitmap the card maps to.
127 HeapBitmap* bitmap = 0;
128 for (BitmapMap::iterator cur = bitmaps_.begin(); cur != bitmaps_.end(); ++cur) {
129 if (cur->first->Contains(reinterpret_cast<Object*>(card_table->AddrFromCard(card)))) {
130 bitmap = cur->second;
131 break;
132 }
133 }
134 DCHECK(bitmap != NULL);
135
136 uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
137 uintptr_t end = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card + 1));
138
139 // Clear the mod-union bitmap range corresponding to this card so that we
140 // don't have any objects marked which do not reach the alloc space.
141 bitmap->VisitRange(start, end, HeapBitmap::ClearVisitor(bitmap));
142
143 // At this point we need to update the mod-union bitmap to contain all the
144 // objects which reach the alloc space.
145 ModUnionVisitor visitor(mark_sweep, bitmap);
146 heap_->GetLiveBits()->VisitMarkedRange(start, end, visitor);
147 }
148}
149
150void ModUnionTableBitmap::MarkReferences(MarkSweep* mark_sweep) {
151 // Some tests have no image space, and therefore no mod-union bitmap.
152 for (BitmapMap::iterator cur = bitmaps_.begin(); cur != bitmaps_.end(); ++cur) {
153 const Space* space = cur->first;
154 uintptr_t begin = reinterpret_cast<uintptr_t>(space->Begin());
155 uintptr_t end = reinterpret_cast<uintptr_t>(space->End());
156 cur->second->VisitRange(begin, end, MarkSweep::ScanImageRootVisitor, mark_sweep);
157 }
158}
159
160} // namespace art
161