Home | History | Annotate | Download | only in vm
      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 }
    333