1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_GC_ACCOUNTING_BITMAP_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_GC_ACCOUNTING_BITMAP_INL_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include "bitmap.h"
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker #include <memory>
23*795d594fSAndroid Build Coastguard Worker
24*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker #include "base/atomic.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
30*795d594fSAndroid Build Coastguard Worker namespace gc {
31*795d594fSAndroid Build Coastguard Worker namespace accounting {
32*795d594fSAndroid Build Coastguard Worker
AtomicTestAndSetBit(uintptr_t bit_index)33*795d594fSAndroid Build Coastguard Worker inline bool Bitmap::AtomicTestAndSetBit(uintptr_t bit_index) {
34*795d594fSAndroid Build Coastguard Worker CheckValidBitIndex(bit_index);
35*795d594fSAndroid Build Coastguard Worker const size_t word_index = BitIndexToWordIndex(bit_index);
36*795d594fSAndroid Build Coastguard Worker const uintptr_t word_mask = BitIndexToMask(bit_index);
37*795d594fSAndroid Build Coastguard Worker auto* atomic_entry = reinterpret_cast<Atomic<uintptr_t>*>(&bitmap_begin_[word_index]);
38*795d594fSAndroid Build Coastguard Worker uintptr_t old_word;
39*795d594fSAndroid Build Coastguard Worker do {
40*795d594fSAndroid Build Coastguard Worker old_word = atomic_entry->load(std::memory_order_relaxed);
41*795d594fSAndroid Build Coastguard Worker // Fast path: The bit is already set.
42*795d594fSAndroid Build Coastguard Worker if ((old_word & word_mask) != 0) {
43*795d594fSAndroid Build Coastguard Worker DCHECK(TestBit(bit_index));
44*795d594fSAndroid Build Coastguard Worker return true;
45*795d594fSAndroid Build Coastguard Worker }
46*795d594fSAndroid Build Coastguard Worker } while (!atomic_entry->CompareAndSetWeakSequentiallyConsistent(old_word, old_word | word_mask));
47*795d594fSAndroid Build Coastguard Worker DCHECK(TestBit(bit_index));
48*795d594fSAndroid Build Coastguard Worker return false;
49*795d594fSAndroid Build Coastguard Worker }
50*795d594fSAndroid Build Coastguard Worker
TestBit(uintptr_t bit_index)51*795d594fSAndroid Build Coastguard Worker inline bool Bitmap::TestBit(uintptr_t bit_index) const {
52*795d594fSAndroid Build Coastguard Worker CheckValidBitIndex(bit_index);
53*795d594fSAndroid Build Coastguard Worker return (bitmap_begin_[BitIndexToWordIndex(bit_index)] & BitIndexToMask(bit_index)) != 0;
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker template<typename Visitor>
VisitSetBits(uintptr_t bit_start,uintptr_t bit_end,const Visitor & visitor)57*795d594fSAndroid Build Coastguard Worker inline void Bitmap::VisitSetBits(uintptr_t bit_start, uintptr_t bit_end, const Visitor& visitor)
58*795d594fSAndroid Build Coastguard Worker const {
59*795d594fSAndroid Build Coastguard Worker DCHECK_LE(bit_start, bit_end);
60*795d594fSAndroid Build Coastguard Worker CheckValidBitIndex(bit_start);
61*795d594fSAndroid Build Coastguard Worker const uintptr_t index_start = BitIndexToWordIndex(bit_start);
62*795d594fSAndroid Build Coastguard Worker const uintptr_t index_end = BitIndexToWordIndex(bit_end);
63*795d594fSAndroid Build Coastguard Worker if (bit_start != bit_end) {
64*795d594fSAndroid Build Coastguard Worker CheckValidBitIndex(bit_end - 1);
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker
67*795d594fSAndroid Build Coastguard Worker // Index(begin) ... Index(end)
68*795d594fSAndroid Build Coastguard Worker // [xxxxx???][........][????yyyy]
69*795d594fSAndroid Build Coastguard Worker // ^ ^
70*795d594fSAndroid Build Coastguard Worker // | #---- Bit of visit_end
71*795d594fSAndroid Build Coastguard Worker // #---- Bit of visit_begin
72*795d594fSAndroid Build Coastguard Worker //
73*795d594fSAndroid Build Coastguard Worker
74*795d594fSAndroid Build Coastguard Worker // Left edge.
75*795d594fSAndroid Build Coastguard Worker uintptr_t left_edge = bitmap_begin_[index_start];
76*795d594fSAndroid Build Coastguard Worker // Clear the lower bits that are not in range.
77*795d594fSAndroid Build Coastguard Worker left_edge &= ~((static_cast<uintptr_t>(1) << (bit_start % kBitsPerBitmapWord)) - 1);
78*795d594fSAndroid Build Coastguard Worker
79*795d594fSAndroid Build Coastguard Worker // Right edge. Either unique, or left_edge.
80*795d594fSAndroid Build Coastguard Worker uintptr_t right_edge;
81*795d594fSAndroid Build Coastguard Worker
82*795d594fSAndroid Build Coastguard Worker if (index_start < index_end) {
83*795d594fSAndroid Build Coastguard Worker // Left edge != right edge.
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker // Traverse left edge.
86*795d594fSAndroid Build Coastguard Worker if (left_edge != 0) {
87*795d594fSAndroid Build Coastguard Worker const uintptr_t ptr_base = WordIndexToBitIndex(index_start);
88*795d594fSAndroid Build Coastguard Worker do {
89*795d594fSAndroid Build Coastguard Worker const size_t shift = CTZ(left_edge);
90*795d594fSAndroid Build Coastguard Worker visitor(ptr_base + shift);
91*795d594fSAndroid Build Coastguard Worker left_edge ^= static_cast<uintptr_t>(1) << shift;
92*795d594fSAndroid Build Coastguard Worker } while (left_edge != 0);
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker
95*795d594fSAndroid Build Coastguard Worker // Traverse the middle, full part.
96*795d594fSAndroid Build Coastguard Worker for (size_t i = index_start + 1; i < index_end; ++i) {
97*795d594fSAndroid Build Coastguard Worker uintptr_t w = bitmap_begin_[i];
98*795d594fSAndroid Build Coastguard Worker if (w != 0) {
99*795d594fSAndroid Build Coastguard Worker const uintptr_t ptr_base = WordIndexToBitIndex(i);
100*795d594fSAndroid Build Coastguard Worker do {
101*795d594fSAndroid Build Coastguard Worker const size_t shift = CTZ(w);
102*795d594fSAndroid Build Coastguard Worker visitor(ptr_base + shift);
103*795d594fSAndroid Build Coastguard Worker w ^= static_cast<uintptr_t>(1) << shift;
104*795d594fSAndroid Build Coastguard Worker } while (w != 0);
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker }
107*795d594fSAndroid Build Coastguard Worker
108*795d594fSAndroid Build Coastguard Worker // Right edge is unique.
109*795d594fSAndroid Build Coastguard Worker // But maybe we don't have anything to do: visit_end starts in a new word...
110*795d594fSAndroid Build Coastguard Worker if (bit_end == 0) {
111*795d594fSAndroid Build Coastguard Worker // Do not read memory, as it could be after the end of the bitmap.
112*795d594fSAndroid Build Coastguard Worker right_edge = 0;
113*795d594fSAndroid Build Coastguard Worker } else {
114*795d594fSAndroid Build Coastguard Worker right_edge = bitmap_begin_[index_end];
115*795d594fSAndroid Build Coastguard Worker }
116*795d594fSAndroid Build Coastguard Worker } else {
117*795d594fSAndroid Build Coastguard Worker right_edge = left_edge;
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker
120*795d594fSAndroid Build Coastguard Worker // Right edge handling.
121*795d594fSAndroid Build Coastguard Worker right_edge &= ((static_cast<uintptr_t>(1) << (bit_end % kBitsPerBitmapWord)) - 1);
122*795d594fSAndroid Build Coastguard Worker if (right_edge != 0) {
123*795d594fSAndroid Build Coastguard Worker const uintptr_t ptr_base = WordIndexToBitIndex(index_end);
124*795d594fSAndroid Build Coastguard Worker do {
125*795d594fSAndroid Build Coastguard Worker const size_t shift = CTZ(right_edge);
126*795d594fSAndroid Build Coastguard Worker visitor(ptr_base + shift);
127*795d594fSAndroid Build Coastguard Worker right_edge ^= (static_cast<uintptr_t>(1)) << shift;
128*795d594fSAndroid Build Coastguard Worker } while (right_edge != 0);
129*795d594fSAndroid Build Coastguard Worker }
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker
132*795d594fSAndroid Build Coastguard Worker template<bool kSetBit>
ModifyBit(uintptr_t bit_index)133*795d594fSAndroid Build Coastguard Worker inline bool Bitmap::ModifyBit(uintptr_t bit_index) {
134*795d594fSAndroid Build Coastguard Worker CheckValidBitIndex(bit_index);
135*795d594fSAndroid Build Coastguard Worker const size_t word_index = BitIndexToWordIndex(bit_index);
136*795d594fSAndroid Build Coastguard Worker const uintptr_t word_mask = BitIndexToMask(bit_index);
137*795d594fSAndroid Build Coastguard Worker uintptr_t* address = &bitmap_begin_[word_index];
138*795d594fSAndroid Build Coastguard Worker uintptr_t old_word = *address;
139*795d594fSAndroid Build Coastguard Worker if (kSetBit) {
140*795d594fSAndroid Build Coastguard Worker *address = old_word | word_mask;
141*795d594fSAndroid Build Coastguard Worker } else {
142*795d594fSAndroid Build Coastguard Worker *address = old_word & ~word_mask;
143*795d594fSAndroid Build Coastguard Worker }
144*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(TestBit(bit_index), kSetBit);
145*795d594fSAndroid Build Coastguard Worker return (old_word & word_mask) != 0;
146*795d594fSAndroid Build Coastguard Worker }
147*795d594fSAndroid Build Coastguard Worker
148*795d594fSAndroid Build Coastguard Worker } // namespace accounting
149*795d594fSAndroid Build Coastguard Worker } // namespace gc
150*795d594fSAndroid Build Coastguard Worker } // namespace art
151*795d594fSAndroid Build Coastguard Worker
152*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_GC_ACCOUNTING_BITMAP_INL_H_
153