OSDN Git Service

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