Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: net/disk_cache/bitmap.cc

Issue 132031: Disk cache: First pass to add support for sparse entries.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/disk_cache/bitmap.h ('k') | net/disk_cache/bitmap_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/disk_cache/bitmap.h"
6
7 #include "base/logging.h"
8
9 namespace {
10
11 // Returns the number of trailing zeros.
12 int FindLSBSetNonZero(uint32 word) {
13 // Get the LSB, put it on the exponent of a 32 bit float and remove the
14 // mantisa and the bias. This code requires IEEE 32 bit float compliance.
15 float f = static_cast<float>(word & -static_cast<int>(word));
16
17 // We use a union to go around strict-aliasing complains.
18 union {
19 float ieee_float;
20 uint32 as_uint;
21 } x;
22
23 x.ieee_float = f;
24 return (x.as_uint >> 23) - 0x7f;
25 }
26
27 // Returns the index of the first bit set to |value| from |word|. This code
28 // assumes that we'll be able to find that bit.
29 int FindLSBNonEmpty(uint32 word, bool value) {
30 // If we are looking for 0, negate |word| and look for 1.
31 if (!value)
32 word = ~word;
33
34 return FindLSBSetNonZero(word);
35 }
36
37 }
38
39 namespace disk_cache {
40
41 void Bitmap::Resize(int num_bits, bool clear_bits) {
42 DCHECK(alloc_ || !map_);
43 const int old_maxsize = num_bits_;
44 const int old_array_size = array_size_;
45 array_size_ = RequiredArraySize(num_bits);
46
47 if (array_size_ != old_array_size) {
48 uint32* new_map = new uint32[array_size_];
49 // Always clear the unused bits in the last word.
50 new_map[array_size_ - 1] = 0;
51 memcpy(new_map, map_,
52 sizeof(*map_) * std::min(array_size_, old_array_size));
53 if (alloc_)
54 delete[] map_; // No need to check for NULL.
55 map_ = new_map;
56 alloc_ = true;
57 }
58
59 num_bits_ = num_bits;
60 if (old_maxsize < num_bits_ && clear_bits) {
61 SetRange(old_maxsize, num_bits_, false);
62 }
63 }
64
65 void Bitmap::Set(int index, bool value) {
66 DCHECK_LT(index, num_bits_);
67 DCHECK_GE(index, 0);
68 const int i = index & (kIntBits - 1);
69 const int j = index / kIntBits;
70 if (value)
71 map_[j] |= (1 << i);
72 else
73 map_[j] &= ~(1 << i);
74 }
75
76 bool Bitmap::Get(int index) const {
77 DCHECK_LT(index, num_bits_);
78 DCHECK_GE(index, 0);
79 const int i = index & (kIntBits-1);
80 const int j = index / kIntBits;
81 return map_[j] & (1 << i) ? true : false;
82 }
83
84 void Bitmap::Toggle(int index) {
85 DCHECK_LT(index, num_bits_);
86 DCHECK_GE(index, 0);
87 const int i = index & (kIntBits - 1);
88 const int j = index / kIntBits;
89 map_[j] ^= (1 << i);
90 }
91
92 void Bitmap::SetMapElement(int array_index, uint32 value) {
93 DCHECK_LT(array_index, array_size_);
94 DCHECK_GE(array_index, 0);
95 map_[array_index] = value;
96 }
97
98 uint32 Bitmap::GetMapElement(int array_index) const {
99 DCHECK_LT(array_index, array_size_);
100 DCHECK_GE(array_index, 0);
101 return map_[array_index];
102 }
103
104 void Bitmap::SetMap(const uint32* map, int size) {
105 memcpy(map_, map, std::min(size, array_size_) * sizeof(*map_));
106 }
107
108 void Bitmap::SetWordBits(int start, int len, bool value) {
109 DCHECK_LT(len, kIntBits);
110 if (!len)
111 return;
112
113 int word = start / kIntBits;
114 int offset = start % kIntBits;
115
116 uint32 to_add = 0xffffffff << len;
117 to_add = (~to_add) << offset;
118 if (value) {
119 map_[word] |= to_add;
120 } else {
121 map_[word] &= ~to_add;
122 }
123 }
124
125 void Bitmap::SetRange(int begin, int end, bool value) {
126 int start_offset = begin & (kIntBits - 1);
127 if (start_offset) {
128 // Set the bits in the first word.
129 int len = std::min(end - begin, kIntBits - start_offset);
130 SetWordBits(begin, len, value);
131 begin += len;
132 }
133
134 if (begin == end)
135 return;
136
137 // Now set the bits in the last word.
138 int end_offset = end & (kIntBits - 1);
139 end -= end_offset;
140 SetWordBits(end, end_offset, value);
141
142 // Set all the words in the middle.
143 memset(map_ + (begin / kIntBits), (value ? 0xFF : 0x00),
144 ((end / kIntBits) - (begin / kIntBits)) * sizeof(*map_));
145 }
146
147 // Return true if any bit between begin inclusive and end exclusive
148 // is set. 0 <= begin <= end <= bits() is required.
149 bool Bitmap::TestRange(int begin, int end, bool value) const {
150 DCHECK_LT(begin, num_bits_);
151 DCHECK_LE(end, num_bits_);
152 DCHECK_LE(begin, end);
153 DCHECK_GE(begin, 0);
154 DCHECK_GE(end, 0);
155
156 // Return false immediately if the range is empty.
157 if (begin >= end || end <= 0)
158 return false;
159
160 // Calculate the indices of the words containing the first and last bits,
161 // along with the positions of the bits within those words.
162 int word = begin / kIntBits;
163 int offset = begin & (kIntBits - 1);
164 int last_word = (end - 1) / kIntBits;
165 int last_offset = (end - 1) & (kIntBits - 1);
166
167 // If we are looking for zeros, negate the data from the map.
168 uint32 this_word = map_[word];
169 if (!value)
170 this_word = ~this_word;
171
172 // If the range spans multiple words, discard the extraneous bits of the
173 // first word by shifting to the right, and then test the remaining bits.
174 if (word < last_word) {
175 if (this_word >> offset)
176 return true;
177 offset = 0;
178
179 word++;
180 // Test each of the "middle" words that lies completely within the range.
181 while (word < last_word) {
182 this_word = map_[word++];
183 if (!value)
184 this_word = ~this_word;
185 if (this_word)
186 return true;
187 }
188 }
189
190 // Test the portion of the last word that lies within the range. (This logic
191 // also handles the case where the entire range lies within a single word.)
192 const uint32 mask = ((2 << (last_offset - offset)) - 1) << offset;
193
194 this_word = map_[last_word];
195 if (!value)
196 this_word = ~this_word;
197
198 return (this_word & mask) != 0;
199 }
200
201 bool Bitmap::FindNextBit(int* index, int limit, bool value) const {
202 DCHECK_LT(*index, num_bits_);
203 DCHECK_LE(limit, num_bits_);
204 DCHECK_LE(*index, limit);
205 DCHECK_GE(*index, 0);
206 DCHECK_GE(limit, 0);
207
208 const int bit_index = *index;
209 if (bit_index >= limit || limit <= 0)
210 return false;
211
212 // From now on limit != 0, since if it was we would have returned false.
213 int word_index = bit_index >> kLogIntBits;
214 uint32 one_word = map_[word_index];
215
216 // Simple optimization where we can immediately return true if the first
217 // bit is set. This helps for cases where many bits are set, and doesn't
218 // hurt too much if not.
219 if (Get(bit_index) == value)
220 return true;
221
222 const int first_bit_offset = bit_index & (kIntBits - 1);
223
224 // First word is special - we need to mask off leading bits.
225 uint32 mask = 0xFFFFFFFF << first_bit_offset;
226 if (value) {
227 one_word &= mask;
228 } else {
229 one_word |= ~mask;
230 }
231
232 uint32 empty_value = value ? 0 : 0xFFFFFFFF;
233
234 // Loop through all but the last word. Note that 'limit' is one
235 // past the last bit we want to check, and we don't want to read
236 // past the end of "words". E.g. if num_bits_ == 32 only words[0] is
237 // valid, so we want to avoid reading words[1] when limit == 32.
238 const int last_word_index = (limit - 1) >> kLogIntBits;
239 while (word_index < last_word_index) {
240 if (one_word != empty_value) {
241 *index = (word_index << kLogIntBits) + FindLSBNonEmpty(one_word, value);
242 return true;
243 }
244 one_word = map_[++word_index];
245 }
246
247 // Last word is special - we may need to mask off trailing bits. Note that
248 // 'limit' is one past the last bit we want to check, and if limit is a
249 // multiple of 32 we want to check all bits in this word.
250 const int last_bit_offset = (limit - 1) & (kIntBits - 1);
251 mask = 0xFFFFFFFE << last_bit_offset;
252 if (value) {
253 one_word &= ~mask;
254 } else {
255 one_word |= mask;
256 }
257 if (one_word != empty_value) {
258 *index = (word_index << kLogIntBits) + FindLSBNonEmpty(one_word, value);
259 return true;
260 }
261 return false;
262 }
263
264 int Bitmap::FindBits(int* index, int limit, bool value) const {
265 DCHECK_LT(*index, num_bits_);
266 DCHECK_LE(limit, num_bits_);
267 DCHECK_LE(*index, limit);
268 DCHECK_GE(*index, 0);
269 DCHECK_GE(limit, 0);
270
271 if (!FindNextBit(index, limit, value))
272 return false;
273
274 // Now see how many bits have the same value.
275 int end = *index;
276 if (!FindNextBit(&end, limit, !value))
277 return limit - *index;
278
279 return end - *index;
280 }
281
282 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/bitmap.h ('k') | net/disk_cache/bitmap_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698