• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
16 
17 /*
18  * Implementation of an expandable bit vector.
19  */
20 #include "Dalvik.h"
21 
22 #include <stdlib.h>
23 #include <strings.h>
24 
25 #define kBitVectorGrowth    4   /* increase by 4 u4s when limit hit */
26 
27 
28 /*
29  * Allocate a bit vector with enough space to hold at least the specified
30  * number of bits.
31  */
dvmAllocBitVector(unsigned int startBits,bool expandable)32 BitVector* dvmAllocBitVector(unsigned int startBits, bool expandable)
33 {
34     BitVector* bv;
35     unsigned int count;
36 
37     assert(sizeof(bv->storage[0]) == 4);        /* assuming 32-bit units */
38 
39     bv = (BitVector*) malloc(sizeof(BitVector));
40 
41     count = (startBits + 31) >> 5;
42 
43     bv->storageSize = count;
44     bv->expandable = expandable;
45     bv->storage = (u4*) malloc(count * sizeof(u4));
46     memset(bv->storage, 0x00, count * sizeof(u4));
47     return bv;
48 }
49 
50 /*
51  * Free a BitVector.
52  */
dvmFreeBitVector(BitVector * pBits)53 void dvmFreeBitVector(BitVector* pBits)
54 {
55     if (pBits == NULL)
56         return;
57 
58     free(pBits->storage);
59     free(pBits);
60 }
61 
62 /*
63  * "Allocate" the first-available bit in the bitmap.
64  *
65  * This is not synchronized.  The caller is expected to hold some sort of
66  * lock that prevents multiple threads from executing simultaneously in
67  * dvmAllocBit/dvmFreeBit.
68  */
dvmAllocBit(BitVector * pBits)69 int dvmAllocBit(BitVector* pBits)
70 {
71     unsigned int word, bit;
72 
73 retry:
74     for (word = 0; word < pBits->storageSize; word++) {
75         if (pBits->storage[word] != 0xffffffff) {
76             /*
77              * There are unallocated bits in this word.  Return the first.
78              */
79             bit = ffs(~(pBits->storage[word])) -1;
80             assert(bit < 32);
81             pBits->storage[word] |= 1 << bit;
82             return (word << 5) | bit;
83         }
84     }
85 
86     /*
87      * Ran out of space, allocate more if we're allowed to.
88      */
89     if (!pBits->expandable)
90         return -1;
91 
92     pBits->storage = (u4*)realloc(pBits->storage,
93                     (pBits->storageSize + kBitVectorGrowth) * sizeof(u4));
94     memset(&pBits->storage[pBits->storageSize], 0x00,
95         kBitVectorGrowth * sizeof(u4));
96     pBits->storageSize += kBitVectorGrowth;
97     goto retry;
98 }
99 
100 /*
101  * Mark the specified bit as "set".
102  */
dvmSetBit(BitVector * pBits,unsigned int num)103 void dvmSetBit(BitVector* pBits, unsigned int num)
104 {
105     if (num >= pBits->storageSize * sizeof(u4) * 8) {
106         if (!pBits->expandable) {
107             LOGE("Attempt to set bit outside valid range (%d, limit is %d)",
108                 num, pBits->storageSize * sizeof(u4) * 8);
109             dvmAbort();
110         }
111 
112         /* Round up to word boundaries for "num+1" bits */
113         unsigned int newSize = (num + 1 + 31) >> 5;
114         assert(newSize > pBits->storageSize);
115         pBits->storage = (u4*)realloc(pBits->storage, newSize * sizeof(u4));
116         if (pBits->storage == NULL) {
117             LOGE("BitVector expansion to %d failed", newSize * sizeof(u4));
118             dvmAbort();
119         }
120         memset(&pBits->storage[pBits->storageSize], 0x00,
121             (newSize - pBits->storageSize) * sizeof(u4));
122         pBits->storageSize = newSize;
123     }
124 
125     pBits->storage[num >> 5] |= 1 << (num & 0x1f);
126 }
127 
128 /*
129  * Mark the specified bit as "clear".
130  */
dvmClearBit(BitVector * pBits,unsigned int num)131 void dvmClearBit(BitVector* pBits, unsigned int num)
132 {
133     assert(num < pBits->storageSize * sizeof(u4) * 8);
134 
135     pBits->storage[num >> 5] &= ~(1 << (num & 0x1f));
136 }
137 
138 /*
139  * Mark all bits bit as "clear".
140  */
dvmClearAllBits(BitVector * pBits)141 void dvmClearAllBits(BitVector* pBits)
142 {
143     unsigned int count = pBits->storageSize;
144     memset(pBits->storage, 0, count * sizeof(u4));
145 }
146 
147 /*
148  * Mark specified number of bits as "set". Cannot set all bits like ClearAll
149  * since there might be unused bits - setting those to one will confuse the
150  * iterator.
151  */
dvmSetInitialBits(BitVector * pBits,unsigned int numBits)152 void dvmSetInitialBits(BitVector* pBits, unsigned int numBits)
153 {
154     unsigned int idx;
155     assert(((numBits + 31) >> 5) <= pBits->storageSize);
156     for (idx = 0; idx < (numBits >> 5); idx++) {
157         pBits->storage[idx] = -1;
158     }
159     unsigned int remNumBits = numBits & 0x1f;
160     if (remNumBits) {
161         pBits->storage[idx] = (1 << remNumBits) - 1;
162     }
163 }
164 
165 /*
166  * Determine whether or not the specified bit is set.
167  */
dvmIsBitSet(const BitVector * pBits,unsigned int num)168 bool dvmIsBitSet(const BitVector* pBits, unsigned int num)
169 {
170     assert(num < pBits->storageSize * sizeof(u4) * 8);
171 
172     unsigned int val = pBits->storage[num >> 5] & (1 << (num & 0x1f));
173     return (val != 0);
174 }
175 
176 /*
177  * Count the number of bits that are set.
178  */
dvmCountSetBits(const BitVector * pBits)179 int dvmCountSetBits(const BitVector* pBits)
180 {
181     unsigned int word;
182     unsigned int count = 0;
183 
184     for (word = 0; word < pBits->storageSize; word++) {
185         u4 val = pBits->storage[word];
186 
187         if (val != 0) {
188             if (val == 0xffffffff) {
189                 count += 32;
190             } else {
191                 /* count the number of '1' bits */
192                 while (val != 0) {
193                     val &= val - 1;
194                     count++;
195                 }
196             }
197         }
198     }
199 
200     return count;
201 }
202 
203 /*
204  * If the vector sizes don't match, log an error and abort.
205  */
checkSizes(const BitVector * bv1,const BitVector * bv2)206 static void checkSizes(const BitVector* bv1, const BitVector* bv2)
207 {
208     if (bv1->storageSize != bv2->storageSize) {
209         LOGE("Mismatched vector sizes (%d, %d)",
210             bv1->storageSize, bv2->storageSize);
211         dvmAbort();
212     }
213 }
214 
215 /*
216  * Copy a whole vector to the other. Only do that when the both vectors have
217  * the same size.
218  */
dvmCopyBitVector(BitVector * dest,const BitVector * src)219 void dvmCopyBitVector(BitVector *dest, const BitVector *src)
220 {
221     /* if dest is expandable and < src, we could expand dest to match */
222     checkSizes(dest, src);
223 
224     memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
225 }
226 
227 /*
228  * Intersect two bit vectors and store the result to the dest vector.
229  */
dvmIntersectBitVectors(BitVector * dest,const BitVector * src1,const BitVector * src2)230 bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
231                             const BitVector *src2)
232 {
233     if (dest->storageSize != src1->storageSize ||
234         dest->storageSize != src2->storageSize ||
235         dest->expandable != src1->expandable ||
236         dest->expandable != src2->expandable)
237         return false;
238 
239     unsigned int idx;
240     for (idx = 0; idx < dest->storageSize; idx++) {
241         dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
242     }
243     return true;
244 }
245 
246 /*
247  * Unify two bit vectors and store the result to the dest vector.
248  */
dvmUnifyBitVectors(BitVector * dest,const BitVector * src1,const BitVector * src2)249 bool dvmUnifyBitVectors(BitVector *dest, const BitVector *src1,
250                         const BitVector *src2)
251 {
252     if (dest->storageSize != src1->storageSize ||
253         dest->storageSize != src2->storageSize ||
254         dest->expandable != src1->expandable ||
255         dest->expandable != src2->expandable)
256         return false;
257 
258     unsigned int idx;
259     for (idx = 0; idx < dest->storageSize; idx++) {
260         dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
261     }
262     return true;
263 }
264 
265 /*
266  * Compare two bit vectors and return true if difference is seen.
267  */
dvmCompareBitVectors(const BitVector * src1,const BitVector * src2)268 bool dvmCompareBitVectors(const BitVector *src1, const BitVector *src2)
269 {
270     if (src1->storageSize != src2->storageSize ||
271         src1->expandable != src2->expandable)
272         return true;
273 
274     unsigned int idx;
275     for (idx = 0; idx < src1->storageSize; idx++) {
276         if (src1->storage[idx] != src2->storage[idx]) return true;
277     }
278     return false;
279 }
280 
281 /* Initialize the iterator structure */
dvmBitVectorIteratorInit(BitVector * pBits,BitVectorIterator * iterator)282 void dvmBitVectorIteratorInit(BitVector* pBits, BitVectorIterator* iterator)
283 {
284     iterator->pBits = pBits;
285     iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
286     iterator->idx = 0;
287 }
288 
289 /* Return the next position set to 1. -1 means end-of-element reached */
dvmBitVectorIteratorNext(BitVectorIterator * iterator)290 int dvmBitVectorIteratorNext(BitVectorIterator* iterator)
291 {
292     const BitVector* pBits = iterator->pBits;
293     u4 bitIndex = iterator->idx;
294 
295     assert(iterator->bitSize == pBits->storageSize * sizeof(u4) * 8);
296     if (bitIndex >= iterator->bitSize) return -1;
297 
298     for (; bitIndex < iterator->bitSize; bitIndex++) {
299         unsigned int wordIndex = bitIndex >> 5;
300         unsigned int mask = 1 << (bitIndex & 0x1f);
301         if (pBits->storage[wordIndex] & mask) {
302             iterator->idx = bitIndex+1;
303             return bitIndex;
304         }
305     }
306     /* No more set bits */
307     return -1;
308 }
309 
310 
311 /*
312  * Merge the contents of "src" into "dst", checking to see if this causes
313  * any changes to occur.  This is a logical OR.
314  *
315  * Returns "true" if the contents of the destination vector were modified.
316  */
dvmCheckMergeBitVectors(BitVector * dst,const BitVector * src)317 bool dvmCheckMergeBitVectors(BitVector* dst, const BitVector* src)
318 {
319     bool changed = false;
320 
321     checkSizes(dst, src);
322 
323     unsigned int idx;
324     for (idx = 0; idx < dst->storageSize; idx++) {
325         u4 merged = src->storage[idx] | dst->storage[idx];
326         if (dst->storage[idx] != merged) {
327             dst->storage[idx] = merged;
328             changed = true;
329         }
330     }
331 
332     return changed;
333 }
334